You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-dev@xerces.apache.org by "Ishara Karunarathna (JIRA)" <xe...@xml.apache.org> on 2011/06/29 05:11:28 UTC

[jira] [Commented] (XERCESJ-1113) [GSoC]: Support for xml:id

    [ https://issues.apache.org/jira/browse/XERCESJ-1113?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13056966#comment-13056966 ] 

Ishara Karunarathna commented on XERCESJ-1113:
----------------------------------------------

Hi Michael and Devs, 

Here I have posted the latest implemented code for xml:id parser component. And I want to know suggestions and comments on my approach.


package org.apache.xerces.xmlID;

import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.impl.dtd.XMLAttributeDecl;
import org.apache.xerces.impl.dtd.XMLSimpleType;
import org.apache.xerces.impl.dv.DTDDVFactory;
import org.apache.xerces.impl.dv.DatatypeValidator;
import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
import org.apache.xerces.impl.dv.dtd.IDDatatypeValidator;
import org.apache.xerces.impl.msg.XMLMessageFormatter;
import org.apache.xerces.impl.validation.ValidationManager;
import org.apache.xerces.impl.validation.ValidationState;
import org.apache.xerces.util.SymbolTable;
import org.apache.xerces.util.XMLSymbols;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.XMLDocumentHandler;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.grammars.XMLGrammarPool;
import org.apache.xerces.xni.parser.XMLComponent;
import org.apache.xerces.xni.parser.XMLComponentManager;
import org.apache.xerces.xni.parser.XMLConfigurationException;
import org.apache.xerces.xni.parser.XMLDocumentFilter;
import org.apache.xerces.xni.parser.XMLDocumentSource;


public class XmlIDHandler implements XMLDocumentFilter, XMLComponent {
	
    // property identifier:  ValidationManager
    protected static final String VALIDATION_MANAGER =
        Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
    
    // updated during reset
    protected ValidationManager fValidationManager = null;
    
    // features

    /** Namespaces. */
    protected boolean fNamespaces;
    
    /** Validation. */
    protected boolean fValidation;

    /** Validation against only DTD */
    protected boolean fDTDValidation;   
  
       // XML document version
    private String version = "0";  
   	
	 /** Datatype validator: ID. */
	//protected DatatypeValidator fValID;
	protected IDDatatypeValidator fValID = new IDDatatypeValidator();
	
	 // validation state
    protected final ValidationState fValidationState = new ValidationState();
    
    /** Error reporter. */
    protected XMLErrorReporter fErrorReporter;
    
    /** Temporary string buffers. */
    private final StringBuffer fBuffer = new StringBuffer();
    
    /** Temporary atribute declaration. */
    private final XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
    
    // handlers

    /** Document handler. */
    protected XMLDocumentHandler fDocumentHandler;

    protected XMLDocumentSource fDocumentSource;
    
    /** Current element index. */
    private int fCurrentElementIndex = -1;
    
    /** Datatype validator factory. */
    protected DTDDVFactory fDatatypeValidatorFactory;

	@Override
	public void characters(XMLString text, Augmentations augs)
			throws XNIException {

		 // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.characters(text, augs);
        }
		
	}

	@Override
	public void comment(XMLString text, Augmentations augs) throws XNIException {
		
		// call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.comment(text, augs);
        }
	}

	@Override
	public void doctypeDecl(String rootElement, String publicId, String systemId,
			Augmentations augs) throws XNIException {
		
		 // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
        }
		
	}

	@Override
	public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
			throws XNIException {
		
		  if (fDocumentHandler !=null) {
	            fDocumentHandler.emptyElement(element, attributes, augs);
	        }
		
	}

	@Override
	public void endCDATA(Augmentations augs) throws XNIException {
		
		 // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.endCDATA(augs);
        }
		
	}

	@Override
	public void endDocument(Augmentations augs) throws XNIException {
		
		 // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.endDocument(augs);
        }
		
	}

	@Override
	public void endElement(QName element, Augmentations augs) throws XNIException {
		
		// call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.endElement(element,augs);
        }
	}

	@Override
	public void endGeneralEntity(String name, Augmentations augs)
			throws XNIException {
		 // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.endGeneralEntity(name, augs);
        }
		
	}

	@Override
	public XMLDocumentSource getDocumentSource() {
		return fDocumentSource;
	}

	@Override
	public void ignorableWhitespace(XMLString text, Augmentations augs)
			throws XNIException {
		
		// call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.ignorableWhitespace(text, augs);
        }
		
	}

	@Override
	public void processingInstruction(String target, XMLString data,
			Augmentations augs) throws XNIException {
		
		// call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.processingInstruction(target, data, augs);
        }
		
	}

	@Override
	public void setDocumentSource(XMLDocumentSource source) {
		fDocumentSource = source;
		
	}

	@Override
	public void startCDATA(Augmentations augs) throws XNIException {
		
		// call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.startCDATA(augs);
        }
		
	}

	@Override
	public void startDocument(XMLLocator locator, String encoding,
			NamespaceContext namespaceContext, Augmentations augs) throws XNIException {
		
		if (fDocumentHandler != null) {
            fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
        }
		
	}

	
	public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
			throws XNIException {
		System.out.println("xmlid handler");
		if (version.equals("1.1")){
			if (attributes.getIndex("xml:id") == 0){
				fCurrentElementIndex = attributes.getIndex("xml:id");
	    		addXmlIDAttrsAndValidate(element, fCurrentElementIndex, attributes);
	    	}
		}
		
		
	        // call handlers
	        if (fDocumentHandler != null) {
	            fDocumentHandler.startElement(element, attributes, augs);

	        }
		
	}

	@Override
	public void startGeneralEntity(String name, XMLResourceIdentifier identifier,
			String encoding, Augmentations augs) throws XNIException {
		
		 if (fDocumentHandler != null) {
	            fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
	        }
		
	}

	@Override
	public void textDecl(String version, String encoding, Augmentations augs)
			throws XNIException {
		// call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.textDecl(version, encoding, augs);
        }
		
	}
	

	public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
    throws XNIException {
		
		if (version.equals("1.1")){
			setVersion(version);
			
		}
        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
        }

    } // xmlDecl(String,String,String)

	private void setVersion(String version) {
		this.version = version;
		
	}

	@Override
	public XMLDocumentHandler getDocumentHandler() {		
		return fDocumentHandler;
	}

	@Override
	public void setDocumentHandler(XMLDocumentHandler documentHandler) {
		 fDocumentHandler = documentHandler;
		
	}
	
	 /** Add xml:ids and validate. */
    protected void addXmlIDAttrsAndValidate(QName elementName, int elementIndex, 
                                               XMLAttributes attributes) {
    	
    	int attrCount = attributes.getLength();
        for (int i = 0; i < attrCount; i++) {
            String attrRawName = attributes.getQName(i);
            
            boolean changedByNormalization = false;
            String oldValue = attributes.getValue(i);
            String attrValue = oldValue;
            changedByNormalization = normalizeAttrValue(attributes, i);
            attrValue = attributes.getValue(i);
            
         // if ( fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ID ) 
       	 if ( true ) {
       		 //c fTempAttDecl is not define
                    validateXmlIDAttribute(elementName, attrValue, fTempAttDecl);
                }
            
        }
    	
    	
    }

	private void validateXmlIDAttribute(QName element, String attValue,
			XMLAttributeDecl attributeDecl) throws XNIException {
		configure();
		try {
            fValID.validate(attValue, fValidationState);
        }
        catch (InvalidDatatypeValueException ex) {
            fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                       ex.getKey(),
                                       ex.getArgs(),
                                       XMLErrorReporter.SEVERITY_ERROR );
        }
	}
	
    private void configure() {
    	 
             try {
                 //REVISIT: datatypeRegistry + initialization of datatype 
                 //         why do we cast to ListDatatypeValidator?
            	 //fDatatypeValidatorFactory = (DTDDVFactory)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY);
         		
                 //fValID       = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDSymbol);

             }
             catch (Exception e) {
                 // should never happen
                 e.printStackTrace(System.err);
             }

        
	}

	private boolean normalizeAttrValue(XMLAttributes attributes, int index) {
    	
        // vars
        boolean leadingSpace = true;
        boolean spaceStart = false;
        boolean readingNonSpace = false;
        int count = 0;
        int eaten = 0;
        String attrValue = attributes.getValue(index);
        System.out.println(attrValue);
        char[] attValue = new char[attrValue.length()];

        fBuffer.setLength(0);
        attrValue.getChars(0, attrValue.length(), attValue, 0);
        for (int i = 0; i < attValue.length; i++) {

            if (attValue[i] == ' ') {

                // now the tricky part
                if (readingNonSpace) {
                    spaceStart = true;
                    readingNonSpace = false;
                }

                if (spaceStart && !leadingSpace) {
                    spaceStart = false;
                    fBuffer.append(attValue[i]);
                    count++;
                }
                else {
                    if (leadingSpace || !spaceStart) {
                        eaten ++;
                        /*** BUG #3512 ***
                        int entityCount = attributes.getEntityCount(index);
                        for (int j = 0;  j < entityCount; j++) {
                            int offset = attributes.getEntityOffset(index, j);
                            int length = attributes.getEntityLength(index, j);
                            if (offset <= i-eaten+1) {
                                if (offset+length >= i-eaten+1) {
                                    if (length > 0)
                                        length--;
                                }
                            } 
                            else {
                                if (offset > 0)
                                    offset--;
                            }
                            attributes.setEntityOffset(index, j, offset);
                            attributes.setEntityLength(index, j, length);
                        }
                        /***/
                    }
                }

            }
            else {
                readingNonSpace = true;
                spaceStart = false;
                leadingSpace = false;
                fBuffer.append(attValue[i]);
                count++;
            }
        }

        // check if the last appended character is a space.
        if (count > 0 && fBuffer.charAt(count-1) == ' ') {
            fBuffer.setLength(count-1);
            /*** BUG #3512 ***
            int entityCount = attributes.getEntityCount(index);
            for (int j=0;  j < entityCount; j++) {
                int offset = attributes.getEntityOffset(index, j);
                int length = attributes.getEntityLength(index, j);
                if (offset < count-1) {
                    if (offset+length == count) {
                        length--;
                    }
                } 
                else {
                    offset--;
                }
                attributes.setEntityOffset(index, j, offset);
                attributes.setEntityLength(index, j, length);
            }
            /***/
        }
        String newValue = fBuffer.toString();
        attributes.setValue(index, newValue);
        return ! attrValue.equals(newValue);
    }

	@Override
	public Boolean getFeatureDefault(String featureId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object getPropertyDefault(String propertyId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String[] getRecognizedFeatures() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String[] getRecognizedProperties() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void reset(XMLComponentManager componentManager)
			throws XMLConfigurationException {

        fCurrentElementIndex = -1;
        

		fValidationState.resetIDTables();
	    
 

        fValidationManager= (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
        fValidationManager.addValidationState(fValidationState);      
        fValidationState.setUsingNamespaces(fNamespaces);
        
        // get needed components
        fErrorReporter = (XMLErrorReporter)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.ERROR_REPORTER_PROPERTY);
       
    
		
	}

	@Override
	public void setFeature(String featureId, boolean state)
			throws XMLConfigurationException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setProperty(String propertyId, Object value)
			throws XMLConfigurationException {
		// TODO Auto-generated method stub
		
	}

}


> [GSoC]: Support for xml:id
> --------------------------
>
>                 Key: XERCESJ-1113
>                 URL: https://issues.apache.org/jira/browse/XERCESJ-1113
>             Project: Xerces2-J
>          Issue Type: New Feature
>          Components: XInclude 1.0
>    Affects Versions: 2.7.1
>         Environment: All
>            Reporter: George Cristian Bina
>              Labels: gsoc2011
>
> Hi,
> The XInclude ID support should handle xml:id. This is useful for instance with DocBook or TEI that use Relax NG schemas for validation and also need XInclude support.
> Here it is a patch that adds support for handling xml:id attributes as attributes of ID type.
> Index: C:/george/workspace/xerces/src/org/apache/xerces/xpointer/ShortHandPointer.java
> ===================================================================
> --- C:/george/workspace/xerces/src/org/apache/xerces/xpointer/ShortHandPointer.java	(revision 344362)
> +++ C:/george/workspace/xerces/src/org/apache/xerces/xpointer/ShortHandPointer.java	(working copy)
> @@ -162,6 +162,17 @@
>              }
>          }
>          
> +        if (normalizedValue == null && attributes != null) {
> +        	// Try to see if we can get an xml:id
> +        	for (int i = 0; i < attributes.getLength(); i++) {
> +        		if ("xml".equals(attributes.getPrefix(i)) && 
> +        				"id".equals(attributes.getLocalName(i))) {
> +        			normalizedValue = attributes.getValue(i);
> +        			break;
> +        		}
> +        	}        	
> +        }
> +        
>          if (normalizedValue != null
>                  && normalizedValue.equals(fShortHandPointer)) {
>              return true;
> Best Regards,
> George

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe, e-mail: j-dev-unsubscribe@xerces.apache.org
For additional commands, e-mail: j-dev-help@xerces.apache.org