Package jmri.util.xml

Class XMLUtil


  • public final class XMLUtil
    extends java.lang.Object
    Utility class collecting library methods related to XML processing. org.openide.xml.XMLUtil adapted to work in JMRI. This should maintain strict API conformance to the OpenIDE implementation.
    • Method Summary

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method Description
      static void appendChildElement​(org.w3c.dom.Element parent, org.w3c.dom.Element el, java.lang.String[] order)
      Append a child element to the parent at the specified location.
      static void copyDocument​(org.w3c.dom.Element from, org.w3c.dom.Element to, java.lang.String newNamespace)
      Copy elements from one document to another attaching at the specified element and translating the namespace.
      static org.w3c.dom.Document createDocument​(java.lang.String rootQName, java.lang.String namespaceURI, java.lang.String doctypePublicID, java.lang.String doctypeSystemID)
      Creates an empty DOM document.
      static org.xml.sax.XMLReader createXMLReader()
      Create a simple parser.
      static org.xml.sax.XMLReader createXMLReader​(boolean validate)
      Create a simple parser, possibly validating.
      static org.xml.sax.XMLReader createXMLReader​(boolean validate, boolean namespaceAware)
      Creates a SAX parser.
      static org.xml.sax.ErrorHandler defaultErrorHandler()
      Create an XML error handler that rethrows errors and fatal errors and logs warnings.
      static org.w3c.dom.Element findElement​(org.w3c.dom.Element parent, java.lang.String name, java.lang.String namespace)
      Search for an XML element in the direct children of parent only.
      static java.util.List<org.w3c.dom.Element> findSubElements​(org.w3c.dom.Element parent)
      Find all direct child elements of an element.
      static java.lang.String findText​(org.w3c.dom.Node parent)
      Extract nested text from a node.
      static byte[] fromHex​(char[] hex, int start, int len)
      Decodes data encoded using toHex.
      static org.w3c.dom.Document parse​(org.xml.sax.InputSource input, boolean validate, boolean namespaceAware, org.xml.sax.ErrorHandler errorHandler, org.xml.sax.EntityResolver entityResolver)
      Parses an XML document into a DOM tree.
      static java.lang.String toAttributeValue​(java.lang.String val)
      Escape passed string as XML attibute value (<, &, ' and " will be escaped.
      static java.lang.String toElementContent​(java.lang.String val)
      Escape passed string as XML element content (<, & and > in ]]> sequences).
      static java.lang.String toHex​(byte[] val, int start, int len)
      Can be used to encode values that contain invalid XML characters.
      static org.w3c.dom.Element translateXML​(org.w3c.dom.Element from, java.lang.String namespace)
      Convert an XML fragment from one namespace to another.
      static void validate​(org.w3c.dom.Element data, javax.xml.validation.Schema schema)
      Check whether a DOM tree is valid according to a schema.
      static void write​(org.w3c.dom.Document doc, java.io.OutputStream out, java.lang.String enc)
      Writes a DOM document to a stream.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • createXMLReader

        public static org.xml.sax.XMLReader createXMLReader()
                                                     throws org.xml.sax.SAXException
        Create a simple parser.
        Returns:
        createXMLReader(false, false)
        Throws:
        org.xml.sax.SAXException - if a parser fulfilling given parameters can not be created
      • createXMLReader

        public static org.xml.sax.XMLReader createXMLReader​(boolean validate)
                                                     throws org.xml.sax.SAXException
        Create a simple parser, possibly validating.
        Parameters:
        validate - if true, a validating parser is returned
        Returns:
        createXMLReader(validate, false)
        Throws:
        org.xml.sax.SAXException - if a parser fulfilling given parameters can not be created
      • createXMLReader

        public static org.xml.sax.XMLReader createXMLReader​(boolean validate,
                                                            boolean namespaceAware)
                                                     throws org.xml.sax.SAXException
        Parameters:
        validate - if true, a validating parser is returned
        namespaceAware - if true, a namespace aware parser is returned
        Returns:
        XMLReader configured according to passed parameters
        Throws:
        javax.xml.parsers.FactoryConfigurationError - Application developers should never need to directly catch errors of this type.
        org.xml.sax.SAXException - if a parser fulfilling given parameters can not be created
      • createDocument

        public static org.w3c.dom.Document createDocument​(java.lang.String rootQName,
                                                          java.lang.String namespaceURI,
                                                          java.lang.String doctypePublicID,
                                                          java.lang.String doctypeSystemID)
                                                   throws org.w3c.dom.DOMException
        Creates an empty DOM document. E.g.:
         Document doc = createDocument("book", null, null, null);
         
        creates new DOM of a well-formed document with root element named book.
        Parameters:
        rootQName - qualified name of root element, for example myroot or ns:myroot
        namespaceURI - URI of root element namespace or null
        doctypePublicID - public ID of DOCTYPE or null
        doctypeSystemID - system ID of DOCTYPE or null if no DOCTYPE required and doctypePublicID is also null
        Returns:
        new DOM Document
        Throws:
        org.w3c.dom.DOMException - if new DOM with passed parameters can not be created
        javax.xml.parsers.FactoryConfigurationError - Application developers should never need to directly catch errors of this type.
      • parse

        public static org.w3c.dom.Document parse​(org.xml.sax.InputSource input,
                                                 boolean validate,
                                                 boolean namespaceAware,
                                                 org.xml.sax.ErrorHandler errorHandler,
                                                 org.xml.sax.EntityResolver entityResolver)
                                          throws java.io.IOException,
                                                 org.xml.sax.SAXException
        Parses an XML document into a DOM tree.

        Remember that when parsing XML files you often want to set an explicit entity resolver. For example, consider a file such as this:

         <?xml version="1.0" encoding="UTF-8"?>
         <!DOCTYPE root PUBLIC "-//NetBeans//DTD Foo 1.0//EN" "http://www.netbeans.org/dtds/foo-1_0.dtd">
         <root/>
         

        If you parse this with a null entity resolver, or you use the default resolver (EntityCatalog.getDefault) but do not do anything special with this DTD, you will probably find the parse blocking to make a network connection even when you are not validating. That is because DTDs can be used to define entities and other XML oddities, and are not a pure constraint language like Schema or RELAX-NG.

        There are three basic ways to avoid the network connection.

        1. Register the DTD. This is generally the best thing to do. See EntityCatalog's documentation for details, but for example in your layer use:
           <filesystem>
             <folder name="xml">
               <folder name="entities">
                 <folder name="NetBeans">
                   <file name="DTD_Foo_1_0"
                         url="resources/foo-1_0.dtd">
                     <attr name="hint.originalPublicID"
                           stringvalue="-//NetBeans//DTD Foo 1.0//EN"/>
                   </file>
                 </folder>
               </folder>
             </folder>
           </filesystem>
           

          Now the default system entity catalog will resolve the public ID to the local copy in your module, not the network copy. Additionally, anyone who mounts the "NetBeans Catalog" in the XML Entity Catalogs node in the Runtime tab will be able to use your local copy of the DTD automatically, for validation, code completion, etc. (The network URL should really exist, though, for the benefit of other tools!)

        2. You can also set an explicit entity resolver which maps that particular public ID to some local copy of the DTD, if you do not want to register it globally in the system for some reason. If handed other public IDs, just return null to indicate that the system ID should be loaded.
        3. In some cases where XML parsing is very performance-sensitive, and you know that you do not need validation and furthermore that the DTD defines no infoset (there are no entity or character definitions, etc.), you can speed up the parse. Turn off validation, but also supply a custom entity resolver that does not even bother to load the DTD at all:
           public InputSource resolveEntity(String pubid, String sysid)
               throws SAXException, IOException {
             if (pubid.equals("-//NetBeans//DTD Foo 1.0//EN")) {
               return new InputSource(new ByteArrayInputStream(new byte[0]));
             } else {
               return EntityCatalog.getDefault().resolveEntity(pubid, sysid);
             }
           }
           
        Parameters:
        input - a parser input (for URL users use: new InputSource(url.toString())
        validate - if true validating parser is used
        namespaceAware - if true DOM is created by namespace aware parser
        errorHandler - a error handler to notify about exception (such as defaultErrorHandler()) or null
        entityResolver - SAX entity resolver (such as EntityCatalog#getDefault) or null
        Returns:
        document representing given input
        Throws:
        java.io.IOException - if an I/O problem during parsing occurs
        org.xml.sax.SAXException - is thrown if a parser error occurs
        javax.xml.parsers.FactoryConfigurationError - Application developers should never need to directly catch errors of this type.
      • write

        public static void write​(org.w3c.dom.Document doc,
                                 java.io.OutputStream out,
                                 java.lang.String enc)
                          throws java.io.IOException
        Writes a DOM document to a stream. The precise output format is not guaranteed but this method will attempt to indent it sensibly.

        Important: There might be some problems with <![CDATA[ ]]> sections in the DOM tree you pass into this method. Specifically, some CDATA sections my not be written as CDATA section or may be merged with other CDATA section at the same level. Also if plain text nodes are mixed with CDATA sections at the same level all text is likely to end up in one big CDATA section.
        For nodes that only have one CDATA section this method should work fine.

        Parameters:
        doc - DOM document to be written
        out - data sink
        enc - XML-defined encoding name (for example, "UTF-8")
        Throws:
        java.io.IOException - if JAXP fails or the stream cannot be written to
      • validate

        public static void validate​(org.w3c.dom.Element data,
                                    javax.xml.validation.Schema schema)
                             throws org.xml.sax.SAXException
        Check whether a DOM tree is valid according to a schema. Example of usage:
         Element fragment = ...;
         SchemaFactory f = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
         Schema s = f.newSchema(This.class.getResource("something.xsd"));
         try {
             XMLUtil.validate(fragment, s);
             // valid
         } catch (SAXException x) {
             // invalid
         }
         
        Parameters:
        data - a DOM tree
        schema - a parsed schema
        Throws:
        org.xml.sax.SAXException - if validation failed
        Since:
        org.openide.util 7.17
      • toAttributeValue

        public static java.lang.String toAttributeValue​(java.lang.String val)
                                                 throws java.io.CharConversionException
        Escape passed string as XML attibute value (<, &, ' and " will be escaped. Note: An XML processor returns normalized value that can be different.
        Parameters:
        val - a string to be escaped
        Returns:
        escaped value
        Throws:
        java.io.CharConversionException - if val contains an improper XML character
        Since:
        1.40
      • toElementContent

        public static java.lang.String toElementContent​(java.lang.String val)
                                                 throws java.io.CharConversionException
        Escape passed string as XML element content (<, & and > in ]]> sequences).
        Parameters:
        val - a string to be escaped
        Returns:
        escaped value
        Throws:
        java.io.CharConversionException - if val contains an improper XML character
        Since:
        1.40
      • toHex

        public static java.lang.String toHex​(byte[] val,
                                             int start,
                                             int len)
        Can be used to encode values that contain invalid XML characters. At SAX parser end must be used pair method to get original value.
        Parameters:
        val - data to be converted
        start - offset
        len - count
        Returns:
        the converted data
        Since:
        1.29
      • fromHex

        public static byte[] fromHex​(char[] hex,
                                     int start,
                                     int len)
                              throws java.io.IOException
        Decodes data encoded using toHex.
        Parameters:
        hex - data to be converted
        start - offset
        len - count
        Returns:
        the converted data
        Throws:
        java.io.IOException - if input does not represent hex encoded value
        Since:
        1.29
      • appendChildElement

        public static void appendChildElement​(org.w3c.dom.Element parent,
                                              org.w3c.dom.Element el,
                                              java.lang.String[] order)
                                       throws java.lang.IllegalArgumentException
        Append a child element to the parent at the specified location. Starting with a valid document, append an element according to the schema sequence represented by the order. All existing child elements must be include as well as the new element. The existing child element following the new child is important, as the element will be 'inserted before', not 'inserted after'.
        Parameters:
        parent - parent to which the child will be appended
        el - element to be added
        order - order of the elements which must be followed
        Throws:
        java.lang.IllegalArgumentException - if the order cannot be followed, either a missing existing or new child element is not specified in order
        Since:
        8.4
      • findSubElements

        public static java.util.List<org.w3c.dom.Element> findSubElements​(org.w3c.dom.Element parent)
                                                                   throws java.lang.IllegalArgumentException
        Find all direct child elements of an element. Children which are all-whitespace text nodes or comments are ignored; others cause an exception to be thrown.
        Parameters:
        parent - a parent element in a DOM tree
        Returns:
        a list of direct child elements (may be empty)
        Throws:
        java.lang.IllegalArgumentException - if there are non-element children besides whitespace
        Since:
        8.4
      • findElement

        public static org.w3c.dom.Element findElement​(org.w3c.dom.Element parent,
                                                      java.lang.String name,
                                                      java.lang.String namespace)
                                               throws java.lang.IllegalArgumentException
        Search for an XML element in the direct children of parent only. This compares localName (nodeName if localName is null) to name, and checks the tags namespace with the provided namespace. A null namespace will match any namespace.

        This is differs from the DOM version by:

        • not searching recursively
        • returns a single result
        Parameters:
        parent - a parent element
        name - the intended local name
        namespace - the intended namespace (or null)
        Returns:
        the one child element with that name, or null if none
        Throws:
        java.lang.IllegalArgumentException - if there is multiple elements of the same name
        Since:
        8.4
      • findText

        public static java.lang.String findText​(org.w3c.dom.Node parent)
        Extract nested text from a node. Currently does not handle coalescing text nodes, CDATA sections, etc.
        Parameters:
        parent - a parent element
        Returns:
        the nested text, or null if none was found
        Since:
        8.4
      • translateXML

        public static org.w3c.dom.Element translateXML​(org.w3c.dom.Element from,
                                                       java.lang.String namespace)
        Convert an XML fragment from one namespace to another.
        Parameters:
        from - element to translate
        namespace - namespace to be translated to
        Returns:
        the element in the new namespace
        Since:
        8.4
      • copyDocument

        public static void copyDocument​(org.w3c.dom.Element from,
                                        org.w3c.dom.Element to,
                                        java.lang.String newNamespace)
        Copy elements from one document to another attaching at the specified element and translating the namespace.
        Parameters:
        from - copy the children of this element (exclusive)
        to - where to attach the copied elements
        newNamespace - destination namespace
        Since:
        8.4
      • defaultErrorHandler

        public static org.xml.sax.ErrorHandler defaultErrorHandler()
        Create an XML error handler that rethrows errors and fatal errors and logs warnings.
        Returns:
        a standard error handler
        Since:
        8.4