Prividers a factory API that enables applications to obtain a parser that produces DOM object trees from XML documents.

1 Configuring the factory

Before parsing an XML document, document builder can be configured.

Return Method Description
DocumentBuilderFactory setAttribute(Stirng name, String value) Set the specific attribute name to the value.
DocumentBuilderFactory setCoalescing(boolean coalescing) Specifies that the parser produced by this code will convert CDATA nodes to Text nodes and append it to the adjacent (if any) text node.
DocumentBuilderFactory setEntityResolver(BiFunction<String, String, String> mapping Specifies the function to map the entity name for publicId and systemId.
ArrayList<SAXParseException> setErrorHandler() Installs an error handler and returns an empty array list that will hold errors after parse.
DocumentBuilderFactory setExpandEntityReferences(boolean expandEntityRef) Specifies that the parser produced by this code will expand entity reference nodes.
DocumentBuilderFactory setFeature(String name, boolean value) Set a feature for this DocumentBuilderFactory and DocumentBuilders created by this factory.
DocumentBuilderFactory setIgnoringComments(boolean ignoreComments) Specifies that the parser produced by this code will ignore comments.
DocumentBuilderFactory setIgnoringElementContentWhitespace(boolean whitespace) Specifies that the parsers created by this factory must eliminate whitespace in element content (sometimes known loosely as 'ignorable whitespace') when parsing XML documents (see XML Rec 2.10).
DocumentBuilderFactory setNamespaceAware(boolean awareness) Specifies that the parser produced by this code will provide support for XML namespaces.
DocumentBuilderFactory setSchema(Schema schema) Set the Schema to be used by parsers created from this factory.
DocumentBuilderFactory setValidating(boolean validating) Specifies that the parser produced by this code will validate documents as they are parsed.
DocumentBuilderFactory setXIncludeAware(boolean state) Set state of XInclude processing.
Copy
var dbf = new Ax.xml.DocumentBuilderFactory();
// by default, validating is set to false to avoid network calls for namespace validation
dbf.setValidating(false);
dbf.setNamespaceAware(true);

2 Parsing XML documents

DocumentBuilderFactory parses the content of the given input source as an XML element and return a new DOM Element object. You can buld an XML element using any of the following sources.

Constuctor Description
parse(String text) Builds an XML element from a String
parse(File file) Builds an XML element from a java File
parse(Reader reader) Builds an XML element from a Reader
parse(InputStream in) Builds an XML element from any convertible to InputStream
Copy
var dbf = new Ax.xml.DocumentBuilderFactory();

// Parser XML document from internet URL resource
var xml = dbf.parse(new Ax.net.URL('https://bitbucket.org/deister/axional-docs-resources/raw/master/XML/books.xml'));

console.log(xml);
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
   ...
Copy
const str = `
<bolsa:inversiones xmlns:bolsa="http://www.bolsa.es" xmlns:geograf="http://www.geograf.com">
    <geograf:país geograf:nombre="España">
        <geograf:capital>Madrid</geograf:capital>
        <bolsa:capital>2000€</bolsa:capital>
    </geograf:país>
</bolsa:inversiones>`

var dbf    = new Ax.xml.DocumentBuilderFactory();
var xmlobj = dbf.parse(str);

var xmlroot = xmlobj.getRootElement();
console.log("Root Element: " + xmlroot.getTagName());
console.log("Attr. bolsa.: " + xmlroot.getAttribute("xmlns:bolsa"));

xmlroot.forEach(node => {
    console.log(node.getTagName());
    console.log("  [Text]=> [" + node.getChildCharacterData() + "]");
    if (node.getFirstChildElement()) {
        node.forEach(subnode => {
            console.log("  => " + subnode.getTagName());
            console.log("    => " + subnode.getFirstChildElement());
            console.log("    => " + subnode.getChildCharacterData());
        });
    }
});
Root Element: bolsa:inversiones
Attr. bolsa.: http://www.bolsa.es
geograf:país
  => geograf:capital
    => null
    => Madrid
  => bolsa:capital
    => null
    => 2000€

2.1 Default XML constructor

You can use the default XMLDocument constructor to parse an XML source from either String, File, Blob or URL. This with use a default XMLDocumentBuilder.

Copy
// Load an XML document
var src = new Ax.xml.XMLDocument(new Ax.net.URL('https://bitbucket.org/deister/axional-docs-resources/raw/master/XML/books.xml'));

3 XML validation

The following sections shows how to use DocumentBuilder APIs to provide mechanisms to validate XML documents. You can read more about XML validation:

3.1 DOM validation

DTDs allow for basic control of element and attribute names and the overall structure of an XML document. DTDs are usually simple to write and understand. The following XML document could be validated with the brief DTD that follows.

Copy
<script>

    // The SOURCE XML
    
    var xml = `
<!DOCTYPE contacts SYSTEM "contacts.dtd">
<contacts> 
  <contact title="Sir"> 
    <firstname>Edwin</firstname> 
    <lastname>Dankert</lastname>
  </contact> 
</contacts>
`;

    // The SOURCE DTD

    var dtd = `
<!ELEMENT contacts (contact*)>
<!ATTLIST contacts xsi:noNamespaceSchemaLocation CDATA #IMPLIED>
<!ATTLIST contacts xmlns:xsi CDATA #IMPLIED>

<!ELEMENT contact (firstname,lastname)>
<!ATTLIST contact title (MR|MS|MRS) "MS">

<!ELEMENT firstname (#PCDATA)>
<!ELEMENT lastname (#PCDATA)>
`;

    // Create a document builder
    var factory = new Ax.xml.DocumentBuilderFactory();
    
    // Enable DTD validation
    factory.setValidating(true);
    factory.setNamespaceAware(true);
    
    // Add a entity resolver to return the content of "contacts.dtd"
    factory.setEntityResolver((publicId, systemId) => {
    	console.log("publicId: " + publicId + " systemId:" + systemId);
    	return dtd;
    });
    
    // Get error handler list
    var errors = factory.setErrorHandler();
    
    // Parse the document. Error handler will fill the list of errors
    var doc = factory.parse(xml);

    for (var error of errors) {
    	console.log(error);
    }
    // org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 24; Attribute "title" with value "Sir" must have a value from the list "MR MS MRS ".
    Ax.junit.assertEquals(1, errors.size());

</script>
org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 24; Attribute "title" with value "Sir" must have a value from the list "MR MS MRS ".

3.2 XSD validation

XML Schema is a considerably more powerful validation mechanism than DTD because it adds data types and more sophisticated structure constraints. Namespaces are fully supported in XML Schema.

One of the more intuitively advantageous aspects of XML Schemas is that they are expressed as XML documents. Having a schema expressed in XML means that the information in the schema is programmatically accessible through the same standard XML interfaces you’re likely already working with.

The XML Schema specification is divided into three parts. The first part is called the primer and describes basic usage of XML Schema. The second part is devoted to the structure or content model mechanism. And the final section describes data types.

Copy
<script>

    // SOURCE xml
    var xml = `
<contacts xsi:noNamespaceSchemaLocation="contacts.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
  <contact title="Sir"> 
    <firstname>Edwin</firstname> 
    <lastname>Dankert</lastname>
  </contact> 
</contacts>
`;

    // SOURCE xsd
    var xsd = `
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="contacts">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="contact"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="contact">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="firstname" type="xs:NCName"/>
        <xs:element name="lastname" type="xs:NCName"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
`;

    // Create a document builder factory
    var factory = new Ax.xml.DocumentBuilderFactory();
    factory.setValidating(true);
    factory.setNamespaceAware(true);
    
    // Setup for XSD vaidation
    factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");

    // Add a entity resolver to return the content of "contacts.xsd"
    factory.setEntityResolver((publicId, systemId) => {
    	console.log("Resolve publicId: " + publicId + " systemId:" + systemId);
    	return xsd;
    });
     
    // Get error handler list
    var errors = factory.setErrorHandler();
    
    var doc = factory.parse(xml);
    for (var error of errors) {
    	console.log(error);
    }
    // org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 24; cvc-complex-type.3.2.2: Attribute 'title' is not allowed to appear in element 'contact'.
    Ax.junit.assertEquals(1, errors.size());

</script>
Resolve publicId: null systemId:file:///Users/eclipse-git/axional-server-script/contacts.xsd
org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 24; cvc-complex-type.3.2.2: Attribute 'title' is not allowed to appear in element 'contact'.