Некоторые XML-документы имеют тип определений описанных в стандарте, например, XML-схемы XML или таблиц стилей. DTD-файлы для них полностью предопределенным и хранятся на принимающие W3C.

Для таких документов, SAX-анализатор может избежать ссылки через Интернет с использованием локальной копии DTD-файле. В целях выполнения таких замен, SAX предлагает механизма enity решения. Обработчик ниже показывает ее использования:

<!-- file: purchase-order.dtd -->
<!-- declaration of the root element and its attributes -->
<!ELEMENT purchase-order (purchased-by, order-items)>
<!ATTLIST purchase-order
date   CDATA #REQUIRED
number CDATA #REQUIRED
>
<!ELEMENT purchased-by (address)>
<!ATTLIST purchased-by
name CDATA #REQUIRED
>
<!ELEMENT address (#PCDATA)>
<!-- order-items can contains at least on item -->
<!ELEMENT order-items (item+)>
<!ELEMENT item EMPTY>
<!ATTLIST item
code  CDATA #REQUIRED
type  CDATA #REQUIRED
label CDATA #REQUIRED
>
<!-- file: sample.xml -->
<?xml version="1.0"?>
<!DOCTYPE purchase-order SYSTEM "http://www.my-company.com/order-1.0.dtd">
<!--
XML document may refer DTD-file that
is located somewhere on WEB.
-->
<purchase-order date="2005-10-31" number="12345">
<purchased-by name="My name">
<!--
we comment it to lead an error:
<address>My address</address>
-->
</purchased-by>
<order-items>
<!--
here is an example of empty element
i.e. containing no nested elements
-->
<item code="687" type="CD" label="Some music" />
<item code="129851" type="DVD" label="Some video"/>
</order-items>
</purchase-order>

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;



import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.SAXParseException;

import org.xml.sax.helpers.DefaultHandler;

import org.xml.sax.InputSource;



/**

 * This is a sample of entity-resolvers usage.

 * Resolvers are used to substitute referenced network

 * resourced by local (downloaded) copies.

 */



public class SampleOfResolvingEntities {

    /**

     * Application entry point

     @param args command-line arguments

     */

    public static void main(String[] args) {

        try {

            // creates and returns new instance of SAX-implementation:

            SAXParserFactory factory = SAXParserFactory.newInstance();

            factory.setValidating(true);

            

            // create SAX-parser...

            SAXParser parser = factory.newSAXParser();

            // parser.getXMLReader().setEntityResolver();

            

            // .. define our handler:

            SaxHandler handler = new SaxHandler();

            

            // and parse:

            parser.parse("sample.xml", handler);

            

        catch (Exception ex) {

            ex.printStackTrace(System.out);

        }

    }

    

    /**

     * Our own implementation of SAX handler reading

     * a purchase-order data.

     */

    private static final class SaxHandler extends DefaultHandler {

        

        // handle references occurred in parsed XML:

        public InputSource resolveEntity(String publicId, 

                String systemId) {

            

            // this will resolve network reference to local file:

            if (systemId.equals(

                        "http://www.my-company.com/order-1.0.dtd")) {

                return new InputSource(getClass().getResourceAsStream(

                            "purchase-order.dtd"));

                // return null;

            else {

                // use the default behaviour

                return null;

            }

        }

        

        // we enter to element 'qName':

        public void startElement(String uri, String localName, 

                String qName, Attributes attrsthrows SAXException {

            

            if (qName.equals("purchase-order")) {

            }

        }

        

        // this is called when document is not valid:

        public void error(SAXParseException exthrows SAXException {

            System.out.println("ERROR: [at " 

                    ex.getLineNumber() "] " + ex);

        }

        

        // this is called when document is not well-formed:

        public void fatalError(SAXParseException exthrows SAXException {

            System.out.println("FATAL_ERROR: [at " 

                    ex.getLineNumber() "] " + ex);

        }

        

        public void warning(SAXParseException exthrows SAXException {

            System.out.println("WARNING: [at " 

                    ex.getLineNumber() "] " + ex);

        }

    }

}

Кроме того, элементы, определенные в DTD, XML имеет ряд уже предопределенный Ones. Эти комментарии, символьных данных (CDATA) и т.д. символьных данных текст непосредственно вставляются между начальным и конечным тегами элемента. Он может смешиваться с детьми отметил элементы.

Конкретная реализация SAX-анализатор определяет, будет ли он собирать все CDATA до перехода к обработчику или она передаст его там их возникновения.

Ниже пример определяет, как обрабатывать CDATA блоки:


import java.util.Stack;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;



import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;



/**

 * This example demonstrates how to extract text (CDATA) information

 * from the element in the source XML-document.

 */



public class SampleOfCDataAccess extends DefaultHandler {

  private Stack currentElement = new Stack();



  // we push current element name:

  public void startElement (String uri, String localName,

    String qName, Attributes attrsthrows SAXException {



    currentElement.push(qName);

  }



  public void endElement(String namespaceURI, String localName,

    String qNamethrows SAXException {



    currentElement.pop();

  }



  // this method will be called for each character-section occurred;

  // if the element containes several CDATA-sections mixed with

  // child elements the number of calls depends on SAX-implementation:

  public void characters(char[] ch, int start, int length)

    throws SAXException {



    String cdata = new String(ch, start, length);



    System.out.println("Element '" + currentElement.peek()

      "' contains text: " + cdata);

  }



  public static void main(String[] args) {

    try {

      // creates and returns new instance of SAX-implementation:

      SAXParserFactory factory = SAXParserFactory.newInstance();

      factory.setValidating(true);



      // create SAX-parser...

      SAXParser parser = factory.newSAXParser();





      parser.parse("sample.xml"new SampleOfCDataAccess());



    catch (Exception ex) {

      ex.printStackTrace(System.out);

    }

  }

}

Одновременно с разбором, SAX может выполнять проверку документов. Т.е. если документ имеет DOCTYPE ассоциированные и SAX было сказано, чтобы проверить документ, анализатор будет уведомлять о всех обработчиков данных возникли ошибки.

Обработчик перекрыть ошибки связанные с ними методы для того, чтобы слушать проверку событий. Есть три ошибки уровнях: предупреждения, ошибки и фатальная ошибка. Если ошибка произошла фатально, по умолчанию SAX-анализатор прерывает чтение файлов.

<!-- file: sample.xml -->
<?xml version="1.0"?>
<!DOCTYPE purchase-order [
<!-- declaration of the root element and its attributes -->
<!ELEMENT purchase-order (purchased-by, order-items)>
<!ATTLIST purchase-order
date   CDATA #REQUIRED
number CDATA #REQUIRED
>
<!ELEMENT purchased-by (address)>
<!ATTLIST purchased-by
name CDATA #REQUIRED
>
<!ELEMENT address (#PCDATA)>
<!-- order-items can contains at least on item -->
<!ELEMENT order-items (item+)>
<!ELEMENT item EMPTY>
<!ATTLIST item
code  CDATA #REQUIRED
type  CDATA #REQUIRED
label CDATA #REQUIRED
>
]>
<!--
In order to constrain the contents of XML-document
a DTD-definition may be used.
The DTD-definition can be inserted immediately into
the caption of target XML-file.
-->
<purchase-order date="2005-10-31" number="12345">
<purchased-by name="My name">
<!--
we comment it to lead an error:
<address>My address</address>
-->
</purchased-by>
<order-items>
<!--
here is an example of empty element
i.e. containing no nested elements
-->
<item code="687" type="CD" label="Some music" />
<item code="129851" type="DVD" label="Some video"/>
</order-items>
</purchase-order>

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;



import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.SAXParseException;

import org.xml.sax.helpers.DefaultHandler;



public class SampleOfHandlingErrors {

    /**

     * Application entry point

     @param args command-line arguments

     */

    public static void main(String[] args) {

        try {

            // creates and returns new instance of SAX-implementation:

            SAXParserFactory factory = SAXParserFactory.newInstance();

            factory.setValidating(true);

            

            // create SAX-parser...

            SAXParser parser = factory.newSAXParser();

            

            // .. define our handler:

            SaxHandler handler = new SaxHandler();

            

            // and parse:

            parser.parse("sample.xml", handler);

            

        catch (Exception ex) {

            ex.printStackTrace(System.out);

        }

    }

    

    /**

     * Our own implementation of SAX handler reading

     * a purchase-order data.

     */

    private static final class SaxHandler extends DefaultHandler {

        

        // we enter to element 'qName':

        public void startElement(String uri, String localName, 

                    String qName, Attributes attrsthrows SAXException {

            

            if (qName.equals("purchase-order")) {

                // ... here process element start:

            }

        }

        

        // this is called when document is not valid:

        public void error(SAXParseException exthrows SAXException {

            System.out.println("ERROR: [at " + ex.getLineNumber() +

                    "] " + ex);

        }

        

        // this is called when document is not well-formed:

        public void fatalError(SAXParseException exthrows SAXException {

            System.out.println("FATAL_ERROR: [at " 

                    ex.getLineNumber() "] " + ex);

        }

        

        public void warning(SAXParseException exthrows SAXException {

            System.out.println("WARNING: [at " 

                    ex.getLineNumber() "] " + ex);

        }

    }

}

В дополнение к общим элементом XML-SAX обработка позволяет получить доступ к их атрибутам. Поскольку XML-атрибуты помещаются в распашная тега XML-элементов, обработчик может получить к ним доступ в нее начала элемента методом.

Набор атрибутов representes на карте объект, из которого любой атрибут-значение может быть принято по его имени:

<!-- file: sample.xml -->
<?xml version="1.0"?>
<!--
All XML elements may have attributes.
Sometimes it is more comfortable to use an attribute
instead of nested element.
-->
<purchase-order date="2005-10-31" number="12345">
<purchased-by name="My name">
<!--
since address may be too complex for attribute
value, we place it to a dedicated element
-->
<address>My address</address>
</purchased-by>
<order-items>
<!--
here is an example of empty element
i.e. containing no nested elements
-->
<item code="687" type="CD" label="Some music" />
<item code="129851" type="DVD" label="Some video"/>
</order-items>
</purchase-order>

import javax.xml.parsers.SAXParser;

import org.xml.sax.helpers.DefaultHandler;

import org.xml.sax.SAXException;

import org.xml.sax.Attributes;

import javax.xml.parsers.SAXParserFactory;



/**

 * Here is sample of reading attributes of a given XML element.

 */



public class SampleOfReadingAttributes {

    /**

     * Application entry point

     @param args command-line arguments

     */

    public static void main(String[] args) {

        try {

            // creates and returns new instance of SAX-implementation:

            SAXParserFactory factory = SAXParserFactory.newInstance();

            

            // create SAX-parser...

            SAXParser parser = factory.newSAXParser();

            // .. define our handler:

            SaxHandler handler = new SaxHandler();

            

            // and parse:

            parser.parse("sample.xml", handler);

            

        catch (Exception ex) {

            ex.printStackTrace(System.out);

        }

    }

    

    /**

     * Our own implementation of SAX handler reading

     * a purchase-order data.

     */

    private static final class SaxHandler extends DefaultHandler {

        

        // we enter to element 'qName':

        public void startElement(String uri, String localName,

                String qName, Attributes attrsthrows SAXException {

            

            if (qName.equals("purchase-order")) {

                // order date value as String:

                String date = attrs.getValue("date");

                // order number as a String:

                String number = attrs.getValue("number");

                

                System.out.println("Order #" + number + " date is '" +

                        date + "'");

                

            }

        }

    }

}

Поскольку существует огромное количество DTD-типы и XML-документов с различными поставщиками, мы можем встретиться проблема имя конфликт в данных XML. Это может иметь место, когда мы пытаемся объединить два или более DTD-определений в одну. Для отдельных определений с тем же именем из разных DTD's имена могут быть использованы.

Пространство имен связан с поставщиками уникальный URL-и однозначно определяет тип элемента, он определяет.

С hamespace к URL отображение происходит в documet XML, SAX обработчиком должна быть в состоянии обработать его:


import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;



import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;



/**

 * This example demonstrates how to indicate current position

 * in the source XML-document.

 */



public class SampleOfNamespacePrefixes extends DefaultHandler {

    

    // this will store URI to prefix correspondance:

    private Map namespaceMapping = new HashMap();

    

    // nothing serious, just save a previx declaration:

    public void startPrefixMapping(String prefix, String uri

        throws SAXException {

        namespaceMapping.put(uri, prefix);

    }

    

    // just remove prefix-declaration when its not needed anymore:

    public void endPrefixMapping(String prefixthrows SAXException {

        

        Iterator i = namespaceMapping.keySet().iterator();

        for (; i.hasNext()) {

            String uri = (Stringi.next();

            String uriPrefix = (StringnamespaceMapping.get(uri);

            

            if (prefix.equals(uriPrefix)) {

                namespaceMapping.remove(uri);

                break;

            }

        }

    }

}