All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.om.AttributeCollectionImpl Maven / Gradle / Ivy

Go to download

Provides a basic XSLT 2.0 and XQuery 1.0 processor (W3C Recommendations, January 2007). Command line interfaces and implementations of several Java APIs (DOM, XPath, s9api) are also included.

The newest version!
package net.sf.saxon.om;

import net.sf.saxon.event.LocationProvider;
import org.xml.sax.Attributes;


/**
 * AttributeCollectionImpl is an implementation of both the SAX2 interface Attributes
 * and the Saxon equivalent AttributeCollection.
 *
 * 

As well as providing the information required by the SAX2 interface, an * AttributeCollection can hold type information (as needed to support the JAXP 1.3 * {@link javax.xml.validation.ValidatorHandler} interface), and location information * for debugging. The location information is used in the case of attributes on a result * tree to identify the location in the query or stylesheet from which they were * generated. */ public final class AttributeCollectionImpl implements Attributes, AttributeCollection { // Attribute values are maintained as an array of Strings. Everything else is maintained // in the form of integers. private NamePool namePool; private LocationProvider locationProvider; private String[] values = null; private int[] codes = null; private int used = 0; // Empty attribute collection. The caller is trusted not to try and modify it. public static final AttributeCollection EMPTY_ATTRIBUTE_COLLECTION = new AttributeCollectionImpl(null); // Layout of the integer array. There are RECSIZE integers for each attribute. private static final int RECSIZE = 4; //private static final int NAMECODE = 0; private static final int TYPECODE = 1; private static final int LOCATIONID = 2; private static final int PROPERTIES = 3; /** * Create an empty attribute list. * @param pool the NamePool */ public AttributeCollectionImpl(NamePool pool) { namePool = pool; used = 0; } /** * Set the location provider. This must be set if the methods getSystemId() and getLineNumber() * are to be used to get location information for an attribute. * @param provider the location provider */ public void setLocationProvider(LocationProvider provider) { locationProvider = provider; } /** * Add an attribute to an attribute list. The parameters correspond * to the parameters of the {@link net.sf.saxon.event.Receiver#attribute(int,int,CharSequence,int,int)} * method. There is no check that the name of the attribute is distinct from other attributes * already in the collection: this check must be made by the caller. * * @param nameCode Integer representing the attribute name. * @param typeCode The attribute type code * @param value The attribute value (must not be null) * @param locationId Identifies the attribtue location. * @param properties Attribute properties */ public void addAttribute(int nameCode, int typeCode, String value, long locationId, int properties) { if (values == null) { values = new String[5]; codes = new int[5 * RECSIZE]; used = 0; } if (values.length == used) { int newsize = (used == 0 ? 5 : used * 2); String[] v2 = new String[newsize]; int[] c2 = new int[newsize * RECSIZE]; System.arraycopy(values, 0, v2, 0, used); System.arraycopy(codes, 0, c2, 0, used*RECSIZE); values = v2; codes = c2; } int n = used*RECSIZE; codes[n] = nameCode; codes[n+TYPECODE] = typeCode; codes[n+LOCATIONID] = (int)locationId; codes[n+PROPERTIES] = properties; values[used++] = value; } /** * Set (overwrite) an attribute in the attribute list. The parameters correspond * to the parameters of the {@link net.sf.saxon.event.Receiver#attribute(int,int,CharSequence,int,int)} * method. * @param index Identifies the entry to be replaced * @param nameCode Integer representing the attribute name. * @param typeCode The attribute type code * @param value The attribute value (must not be null) * @param locationId Identifies the attribtue location. * @param properties Attribute properties */ public void setAttribute(int index, int nameCode, int typeCode, String value, long locationId, int properties) { int n = index*RECSIZE; codes[n] = nameCode; codes[n+TYPECODE] = typeCode; codes[n+LOCATIONID] = (int)locationId; codes[n+PROPERTIES] = properties; values[index] = value; } /** * Clear the attribute list. This removes the values but doesn't free the memory used. * free the memory, use clear() then compact(). */ public void clear() { used = 0; } /** * Compact the attribute list to avoid wasting memory */ public void compact() { if (used == 0) { codes = null; values = null; } else if (values.length > used) { String[] v2 = new String[used]; int[] c2 = new int[used * RECSIZE]; System.arraycopy(values, 0, v2, 0, used); System.arraycopy(codes, 0, c2, 0, used*RECSIZE); values = v2; codes = c2; } } /** * Return the number of attributes in the list. * * @return The number of attributes in the list. */ public int getLength() { return (values == null ? 0 : used); } /** * Get the namecode of an attribute (by position). * * @param index The position of the attribute in the list. * @return The display name of the attribute as a string, or null if there * is no attribute at that position. */ public int getNameCode(int index) { if (codes == null) { return -1; } if (index < 0 || index >= used) { return -1; } return codes[(index * RECSIZE)]; } /** * Get the namecode of an attribute (by position). * * @param index The position of the attribute in the list. * @return The type annotation, as the fingerprint of the type name. * The bit {@link net.sf.saxon.om.NodeInfo#IS_DTD_TYPE} represents a DTD-derived type. */ public int getTypeAnnotation(int index) { if (codes == null) { return StandardNames.XS_UNTYPED_ATOMIC; } if (index < 0 || index >= used) { return StandardNames.XS_UNTYPED_ATOMIC; } return codes[index * RECSIZE + TYPECODE]; } /** * Get the locationID of an attribute (by position) * @param index The position of the attribute in the list. * @return The location identifier of the attribute. This can be supplied * to a {@link net.sf.saxon.event.LocationProvider} in order to obtain the * actual system identifier and line number of the relevant location */ public int getLocationId(int index) { if (codes == null) { return -1; } if (index < 0 || index >= used) { return -1; } return codes[index * RECSIZE + LOCATIONID]; } /** * Get the systemId part of the location of an attribute, at a given index. * *

Attribute location information is not available from a SAX parser, so this method * is not useful for getting the location of an attribute in a source document. However, * in a Saxon result document, the location information represents the location in the * stylesheet of the instruction used to generate this attribute, which is useful for * debugging.

* @param index the required attribute * @return the systemId of the location of the attribute */ public String getSystemId(int index) { return locationProvider.getSystemId(getLocationId(index)); } /** * Get the line number part of the location of an attribute, at a given index. * *

Attribute location information is not available from a SAX parser, so this method * is not useful for getting the location of an attribute in a source document. However, * in a Saxon result document, the location information represents the location in the * stylesheet of the instruction used to generate this attribute, which is useful for * debugging.

* @param index the required attribute * @return the line number of the location of the attribute */ public int getLineNumber(int index) { return locationProvider.getLineNumber(getLocationId(index)); } /** * Get the properties of an attribute (by position) * @param index The position of the attribute in the list. * @return The properties of the attribute. This is a set * of bit-settings defined in class {@link net.sf.saxon.event.ReceiverOptions}. The * most interesting of these is {{@link net.sf.saxon.event.ReceiverOptions#DEFAULTED_ATTRIBUTE}, * which indicates an attribute that was added to an element as a result of schema validation. */ public int getProperties(int index) { if (codes == null) { return -1; } if (index < 0 || index >= used) { return -1; } return codes[index * RECSIZE + PROPERTIES]; } /** * Get the prefix of the name of an attribute (by position). * * @param index The position of the attribute in the list. * @return The prefix of the attribute name as a string, or null if there * is no attribute at that position. Returns "" for an attribute that * has no prefix. */ public String getPrefix(int index) { if (codes == null) { return null; } if (index < 0 || index >= used) { return null; } return namePool.getPrefix(getNameCode(index)); } /** * Get the lexical QName of an attribute (by position). * * @param index The position of the attribute in the list. * @return The lexical QName of the attribute as a string, or null if there * is no attribute at that position. */ public String getQName(int index) { if (codes == null) { return null; } if (index < 0 || index >= used) { return null; } return namePool.getDisplayName(getNameCode(index)); } /** * Get the local name of an attribute (by position). * * @param index The position of the attribute in the list. * @return The local name of the attribute as a string, or null if there * is no attribute at that position. */ public String getLocalName(int index) { if (codes == null) { return null; } if (index < 0 || index >= used) { return null; } return namePool.getLocalName(getNameCode(index)); } /** * Get the namespace URI of an attribute (by position). * * @param index The position of the attribute in the list. * @return The local name of the attribute as a string, or null if there * is no attribute at that position. */ public String getURI(int index) { if (codes == null) { return null; } if (index < 0 || index >= used) { return null; } return namePool.getURI(getNameCode(index)); } /** * Get the type of an attribute (by position). This is a SAX2 method, * so it gets the type name as a DTD attribute type, mapped from the * schema type code. * * @param index The position of the attribute in the list. * @return The attribute type as a string ("NMTOKEN" for an * enumeration, and "CDATA" if no declaration was * read), or null if there is no attribute at * that position. */ public String getType(int index) { int typeCode = getTypeAnnotation(index) & NamePool.FP_MASK; switch (typeCode) { case StandardNames.XS_ID: return "ID"; case StandardNames.XS_IDREF: return "IDREF"; case StandardNames.XS_NMTOKEN: return "NMTOKEN"; case StandardNames.XS_ENTITY: return "ENTITY"; case StandardNames.XS_IDREFS: return "IDREFS"; case StandardNames.XS_NMTOKENS: return "NMTOKENS"; case StandardNames.XS_ENTITIES: return "ENTITIES"; default: return "CDATA"; } } /** * Get the type of an attribute (by name). * * @param uri The namespace uri of the attribute. * @param localname The local name of the attribute. * @return The index position of the attribute */ public String getType(String uri, String localname) { int index = findByName(uri, localname); return (index < 0 ? null : getType(index)); } /** * Get the value of an attribute (by position). * * @param index The position of the attribute in the list. * @return The attribute value as a string, or null if * there is no attribute at that position. */ public String getValue(int index) { if (values == null) { return null; } if (index < 0 || index >= used) { return null; } return values[index]; } /** * Get the value of an attribute (by name). * * @param uri The namespace uri of the attribute. * @param localname The local name of the attribute. * @return The index position of the attribute */ public String getValue(String uri, String localname) { int index = findByName(uri, localname); return (index < 0 ? null : getValue(index)); } /** * Get the attribute value using its fingerprint */ public String getValueByFingerprint(int fingerprint) { int index = findByFingerprint(fingerprint); return (index < 0 ? null : getValue(index)); } /** * Get the index of an attribute, from its lexical QName * * @param qname The lexical QName of the attribute. The prefix must match. * @return The index position of the attribute */ public int getIndex(String qname) { if (codes == null) { return -1; } if (qname.indexOf(':') < 0) { return findByName("", qname); } // Searching using prefix+localname is not recommended, but SAX allows it... String[] parts; try { parts = Name11Checker.getInstance().getQNameParts(qname); } catch (QNameException err) { return -1; } String prefix = parts[0]; if (prefix.length() == 0) { return findByName("", qname); } else { String localName = parts[1]; for (int i = 0; i < used; i++) { String lname = namePool.getLocalName(getNameCode(i)); String ppref = namePool.getPrefix(getNameCode(i)); if (localName.equals(lname) && prefix.equals(ppref)) { return i; } } return -1; } } /** * Get the index of an attribute (by name). * * @param uri The namespace uri of the attribute. * @param localname The local name of the attribute. * @return The index position of the attribute */ public int getIndex(String uri, String localname) { return findByName(uri, localname); } /** * Get the index, given the fingerprint. * Return -1 if not found. */ public int getIndexByFingerprint(int fingerprint) { return findByFingerprint(fingerprint); } /** * Get the type of an attribute (by lexical QName). * * @param name The lexical QName of the attribute. * @return The attribute type as a string (e.g. "NMTOKEN", or * "CDATA" if no declaration was read). */ public String getType(String name) { int index = getIndex(name); return getType(index); } /** * Get the value of an attribute (by lexical QName). * * @param name The attribute name (a lexical QName). * The prefix must match the prefix originally used. This method is defined in SAX, but is * not recommended except where the prefix is null. */ public String getValue(String name) { int index = getIndex(name); return getValue(index); } /** * Find an attribute by expanded name * @param uri the namespace uri * @param localName the local name * @return the index of the attribute, or -1 if absent */ private int findByName(String uri, String localName) { if (namePool == null) { return -1; // indicates an empty attribute set } int f = namePool.getFingerprint(uri, localName); if (f == -1) { return -1; } return findByFingerprint(f); } /** * Find an attribute by fingerprint * @param fingerprint the fingerprint representing the name of the required attribute * @return the index of the attribute, or -1 if absent */ private int findByFingerprint(int fingerprint) { if (codes == null) { return -1; } for (int i = 0; i < used; i++) { if (fingerprint == (codes[(i * RECSIZE)] & NamePool.FP_MASK)) { return i; } } return -1; } /** * Determine whether a given attribute has the is-ID property set */ public boolean isId(int index) { return getType(index).equals("ID") || ((getNameCode(index) & NamePool.FP_MASK) == StandardNames.XML_ID); } /** * Determine whether a given attribute has the is-idref property set */ public boolean isIdref(int index) { return false; } } // // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License"); // you may not use this file except in compliance with the License. You may obtain a copy of the // License at http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS IS" basis, // WITHOUT WARRANTY OF ANY KIND, either express or implied. // See the License for the specific language governing rights and limitations under the License. // // The Original Code is: all this file. // // The Initial Developer of the Original Code is Michael H. Kay. // // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved. // // Contributor(s): none. //




© 2015 - 2025 Weber Informatics LLC | Privacy Policy