Select Children And Attributes Feature

This feature enables dynamic selection of XmlObject properties based on their QNames. Also the QNameSet parameter methods could be used, in many cases, to select the elements and attributes that are in the any or anyAttribute wildcard buckets.

The dynamic selection is done using the following XmlObject methods:

    XmlObject[] selectChildren(QName elementName);

    XmlObject[] selectChildren(String elementUri, String elementLocalName);

    XmlObject[] selectChildren(QNameSet elementNameSet);

    XmlObject selectAttribute(QName attributeName);

    XmlObject selectAttribute(String attributeUri, String attributeLocalName);

    XmlObject[] selectAttributes(QNameSet attributeNameSet);

They select the contents of the children elements or attributes with the given name or their name is contained in the given QNameSet.

These are two useful methods on SchemaType to find out the QNameSets of elements or attributes in the wildcard buckets for a given type.

    public QNameSet qnameSetForWildcardElements();

    public QNameSet qnameSetForWildcardAttributes();

Note: The schema specification contains "Element Declarations Consistent" rule, which requires that any definition for <foo> be of exactly the same type even if it's pulled in via a wildcard (http://lists.w3.org/Archives/Public/www-xml-schema-comments/2003OctDec/0029.html). Because of this rule, these two methods will return the qname sets coresponding to the wildcards but without containing the names of the elements or attributes explicitly declared in the SchemaType or it's base types.

Example

Example user code for this feature. See below the schema and the xml instance.

Code

   1         DocDocument document = DocDocument.Factory.parse(xml);
   2         DocDocument.Doc doc = document.getDoc();
   3         Collection errors = new ArrayList();
   4         System.out.println(xml + "\n\nvalid: " + doc.validate(new XmlOptions().setErrorListener(errors)));
   5         printErrors(errors);
   6 
   7         XmlObject xo;
   8         XmlObject[] xos;
   9 
  10         // select a known element
  11         xos = doc.selectChildren(new QName(uri, "int"));
  12         print("1 selectChildren 'int' : ", xos);
  13 
  14         xos = doc.selectChildren(uri, "string");
  15         print("2 selectChildren 'string' : ", xos);
  16 
  17         // elemA
  18         xos = doc.selectChildren(new QName(uri, "elemA"));
  19         print("3 selectChildren 'elemA' : ", xos);
  20 
  21         // select a known attribute
  22         xo = xos[0].selectAttribute(new QName("", "price"));
  23         print("4     selectAttribute 'price' : ", xo);
  24 
  25         // select all attributes
  26         QNameSet qns = QNameSet.forWildcardNamespaceString("##any", uri);
  27         xos = xos[0].selectAttributes(qns);
  28         print("5     selectAttributes set'##any' :", xos);
  29 
  30         // elemB
  31         xos = doc.selectChildren(new QName(uri, "elemB"));
  32         print("6 selectChildren 'elemB' : ", xos);
  33         print("7     selectChildren set'##other' : " , xos[0].selectChildren(QNameSet.forWildcardNamespaceString("##other", uri)));
  34         print("8     selectAttributes set'##other' : ", xos[0].selectAttributes(QNameSet.forWildcardNamespaceString("##other", uri)));
  35 
  36         // elemC
  37         xos = doc.selectChildren(new QName(uri, "elemC"));
  38         print("9 selectChildren 'elemC' : ", xos);
  39         print("10    selectChildren set'##any' : " , xos[0].selectChildren(QNameSet.forWildcardNamespaceString("##any", uri)));
  40 
  41         // select elements in the any buchet by excluding the the known elements
  42         QNameSetBuilder qnsb = new QNameSetBuilder();
  43         qnsb.add(new QName(uri, "someElement"));
  44         qnsb.add(new QName(uri, "aditionalElement"));
  45         qnsb.invert();
  46 
  47         print("11a    selectChildren in the any buchet for typeExtendedC: " , xos[0].selectChildren(qnsb.toQNameSet()));
  48 
  49         print("11b    selectChildren in the any buchet for typeExtendedC: " , xos[0].selectChildren(TypeExtendedC.type.qnameSetForWildcardElements()));
  50 
  51         // select attributes in the any buchet by excluding the the known elements
  52         qnsb = new QNameSetBuilder();
  53         qnsb.add(new QName("", "att1"));
  54         qnsb.add(new QName("", "aditionalAtt"));
  55         qnsb.add(new QName(XSI_URI, "type"));
  56         qnsb.invert();
  57 
  58         print("12a    selectChildren in the any buchet for typeExtendedC: " , xos[0].selectAttributes(qnsb.toQNameSet()));
  59         print("12b    selectChildren in the any buchet for typeExtendedC: " , xos[0].selectAttributes(TypeExtendedC.type.qnameSetForWildcardAttributes()));

Schema

<xs:schema
   xmlns:xs='http://www.w3.org/2001/XMLSchema'
   xmlns='http://xml.apache.org/test/wildcardutil'
   targetNamespace='http://xml.apache.org/test/wildcardutil'
   elementFormDefault='qualified'>

  <xs:element name='doc'>
    <xs:complexType>
      <xs:sequence>
        <xs:choice minOccurs='0' maxOccurs='unbounded'>
          <xs:element name='int' type='xs:int' />
          <xs:element name='string' type='xs:string' />
          <xs:element name='elemA' type='typeA' />
          <xs:element name='elemB' type='typeB' />
          <xs:element name='elemC' type='typeC' />
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="typeA">
    <xs:sequence>
      <xs:any namespace="##any" processContents="lax" minOccurs='0' maxOccurs='unbounded' />
    </xs:sequence>
    <xs:anyAttribute namespace="##any" processContents="lax" />
  </xs:complexType>

  <xs:complexType name="typeB">
    <xs:sequence>
      <xs:element name="someElement" type='xs:int' />

      <xs:any namespace="##other" processContents="lax" minOccurs='0' maxOccurs='unbounded' />
    </xs:sequence>
        <xs:attribute name='att1' type='xs:string' />

    <xs:anyAttribute namespace="##other" processContents="lax" />
  </xs:complexType>

  <xs:complexType name="typeC">
    <xs:sequence>
      <xs:element name="someElement" type='xs:string' />

      <xs:any namespace="##other" processContents="lax" minOccurs='0' maxOccurs='unbounded'  />
    </xs:sequence>
    <xs:attribute name='att1' type='xs:string' />

    <xs:anyAttribute namespace="##other" processContents="lax" />
  </xs:complexType>

  <xs:complexType name="typeExtendedC">
    <xs:complexContent>
      <xs:extension base='typeC'>
        <xs:sequence>
          <xs:element name="aditionalElement" type='xs:string' />
        </xs:sequence>
        <xs:attribute name='aditionalAtt' type='xs:string' />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:element name='topLevelElement' type='xs:string' />

  <xs:attribute name='price' type='xs:float' />
  <xs:attribute name='quant' type='xs:byte' />

</xs:schema>

XML Instance

<doc xmlns='http://xml.apache.org/test/wildcardutil'>
  <int>7</int>
  <string> ... some text ... </string>
  <elemA price='4.321'>
    <topLevelElement> this is wildcard buchet </topLevelElement>
  </elemA>
  <elemB xmlns:p='uri:other_namespace' 
       p:att='attribute in #other namespace'>
    <someElement>2</someElement>
    <p:otherElement> element in #other namespace </p:otherElement>
  </elemB>
  <elemC xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
         xmlns:p='uri_other_namespace' 
         xsi:type='typeExtendedC' 
         att1='attribute from typeC' 
         aditionalAtt='attribute added in type extension' 
         p:validAtt='attribute in any buchet' >
    <someElement> element from typeC </someElement>
    <p:validElement> element in the 'any' buchet for typeExtendedC </p:validElement>
    <aditionalElement> element from typeExtendedC </aditionalElement>
  </elemC>
</doc>

SelectChildrenAndAttributesFeature (last edited 2011-12-19 22:16:45 by fx)