View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements. See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership. The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License. You may obtain a copy of the License at
    9    *
    10   * http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing,
    13   * software distributed under the License is distributed on an
    14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   * KIND, either express or implied. See the License for the
    16   * specific language governing permissions and limitations
    17   * under the License.
    18   */
    19
    20  package org.apache.ws.commons.schema.utils;
    21
    22  import org.w3c.dom.*;
    23
    24  import java.lang.reflect.Method;
    25
    26  /**
    27   * Some useful utility methods.
    28   * This class was modified in Xerces2 with a view to abstracting as
    29   * much as possible away from the representation of the underlying
    30   * parsed structure (i.e., the DOM).  This was done so that, if Xerces
    31   * ever adopts an in-memory representation more efficient than the DOM
    32   * (such as a DTM), we should easily be able to convert our schema
    33   * parsing to utilize it.
    34   *
    35   * @version $ID DOMUtil
    36   */
    37  public class DOMUtil {
    38
    39      private static final String DEFAULT_ENCODING = "UTF-8";
    40
    41  	//
    42      // Constructors
    43      //
    44
    45      /**
    46       * This class cannot be instantiated.
    47       */
    48      protected DOMUtil() {
    49      }
    50
    51      //
    52      // Public static methods
    53      //
    54
    55      /**
    56       * Finds and returns the first child element node.
    57       */
    58      public static Element getFirstChildElement(Node parent) {
    59
    60          // search for node
    61          Node child = parent.getFirstChild();
    62          while (child != null) {
    63              if (child.getNodeType() == Node.ELEMENT_NODE) {
    64                  return (Element) child;
    65              }
    66              child = child.getNextSibling();
    67          }
    68
    69          // not found
    70          return null;
    71
    72      } // getFirstChildElement(Node):Element
    73
    74      /**
    75       * Finds and returns the last child element node.
    76       */
    77      public static Element getLastChildElement(Node parent) {
    78
    79          // search for node
    80          Node child = parent.getLastChild();
    81          while (child != null) {
    82              if (child.getNodeType() == Node.ELEMENT_NODE) {
    83                  return (Element) child;
    84              }
    85              child = child.getPreviousSibling();
    86          }
    87
    88          // not found
    89          return null;
    90
    91      } // getLastChildElement(Node):Element
    92
    93
    94      /**
    95       * Finds and returns the next sibling element node.
    96       */
    97      public static Element getNextSiblingElement(Node node) {
    98
    99          // search for node
    100         Node sibling = node.getNextSibling();
    101         while (sibling != null) {
    102             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
    103                 return (Element) sibling;
    104             }
    105             sibling = sibling.getNextSibling();
    106         }
    107
    108         // not found
    109         return null;
    110
    111     } // getNextSiblingElement(Node):Element
    112
    113     /**
    114      * Finds and returns the first child node with the given name.
    115      */
    116     public static Element getFirstChildElement(Node parent, String elemName) {
    117
    118         // search for node
    119         Node child = parent.getFirstChild();
    120         while (child != null) {
    121             if (child.getNodeType() == Node.ELEMENT_NODE) {
    122                 if (child.getNodeName().equals(elemName)) {
    123                     return (Element) child;
    124                 }
    125             }
    126             child = child.getNextSibling();
    127         }
    128
    129         // not found
    130         return null;
    131
    132     } // getFirstChildElement(Node,String):Element
    133
    134     /**
    135      * Finds and returns the last child node with the given name.
    136      */
    137     public static Element getLastChildElement(Node parent, String elemName) {
    138
    139         // search for node
    140         Node child = parent.getLastChild();
    141         while (child != null) {
    142             if (child.getNodeType() == Node.ELEMENT_NODE) {
    143                 if (child.getNodeName().equals(elemName)) {
    144                     return (Element) child;
    145                 }
    146             }
    147             child = child.getPreviousSibling();
    148         }
    149
    150         // not found
    151         return null;
    152
    153     } // getLastChildElement(Node,String):Element
    154
    155     /**
    156      * Finds and returns the next sibling node with the given name.
    157      */
    158     public static Element getNextSiblingElement(Node node, String elemName) {
    159
    160         // search for node
    161         Node sibling = node.getNextSibling();
    162         while (sibling != null) {
    163             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
    164                 if (sibling.getNodeName().equals(elemName)) {
    165                     return (Element) sibling;
    166                 }
    167             }
    168             sibling = sibling.getNextSibling();
    169         }
    170
    171         // not found
    172         return null;
    173
    174     } // getNextSiblingdElement(Node,String):Element
    175
    176     /**
    177      * Finds and returns the first child node with the given qualified name.
    178      */
    179     public static Element getFirstChildElementNS(Node parent,
    180                                                  String uri, String localpart) {
    181
    182         // search for node
    183         Node child = parent.getFirstChild();
    184         while (child != null) {
    185             if (child.getNodeType() == Node.ELEMENT_NODE) {
    186                 String childURI = child.getNamespaceURI();
    187                 if (childURI != null && childURI.equals(uri) &&
    188                         child.getLocalName().equals(localpart)) {
    189                     return (Element) child;
    190                 }
    191             }
    192             child = child.getNextSibling();
    193         }
    194
    195         // not found
    196         return null;
    197
    198     } // getFirstChildElementNS(Node,String,String):Element
    199
    200     /**
    201      * Finds and returns the last child node with the given qualified name.
    202      */
    203     public static Element getLastChildElementNS(Node parent,
    204                                                 String uri, String localpart) {
    205
    206         // search for node
    207         Node child = parent.getLastChild();
    208         while (child != null) {
    209             if (child.getNodeType() == Node.ELEMENT_NODE) {
    210                 String childURI = child.getNamespaceURI();
    211                 if (childURI != null && childURI.equals(uri) &&
    212                         child.getLocalName().equals(localpart)) {
    213                     return (Element) child;
    214                 }
    215             }
    216             child = child.getPreviousSibling();
    217         }
    218
    219         // not found
    220         return null;
    221
    222     } // getLastChildElementNS(Node,String,String):Element
    223
    224     /**
    225      * Finds and returns the next sibling node with the given qualified name.
    226      */
    227     public static Element getNextSiblingElementNS(Node node,
    228                                                   String uri, String localpart) {
    229
    230         // search for node
    231         Node sibling = node.getNextSibling();
    232         while (sibling != null) {
    233             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
    234                 String siblingURI = sibling.getNamespaceURI();
    235                 if (siblingURI != null && siblingURI.equals(uri) &&
    236                         sibling.getLocalName().equals(localpart)) {
    237                     return (Element) sibling;
    238                 }
    239             }
    240             sibling = sibling.getNextSibling();
    241         }
    242
    243         // not found
    244         return null;
    245
    246     } // getNextSiblingdElementNS(Node,String,String):Element
    247
    248     /**
    249      * Finds and returns the first child node with the given name.
    250      */
    251     public static Element getFirstChildElement(Node parent, String elemNames[]) {
    252
    253         // search for node
    254         Node child = parent.getFirstChild();
    255         while (child != null) {
    256             if (child.getNodeType() == Node.ELEMENT_NODE) {
    257                 for (int i = 0; i < elemNames.length; i++) {
    258                     if (child.getNodeName().equals(elemNames[i])) {
    259                         return (Element) child;
    260                     }
    261                 }
    262             }
    263             child = child.getNextSibling();
    264         }
    265
    266         // not found
    267         return null;
    268
    269     } // getFirstChildElement(Node,String[]):Element
    270
    271     /**
    272      * Finds and returns the last child node with the given name.
    273      */
    274     public static Element getLastChildElement(Node parent, String elemNames[]) {
    275
    276         // search for node
    277         Node child = parent.getLastChild();
    278         while (child != null) {
    279             if (child.getNodeType() == Node.ELEMENT_NODE) {
    280                 for (int i = 0; i < elemNames.length; i++) {
    281                     if (child.getNodeName().equals(elemNames[i])) {
    282                         return (Element) child;
    283                     }
    284                 }
    285             }
    286             child = child.getPreviousSibling();
    287         }
    288
    289         // not found
    290         return null;
    291
    292     } // getLastChildElement(Node,String[]):Element
    293
    294     /**
    295      * Finds and returns the next sibling node with the given name.
    296      */
    297     public static Element getNextSiblingElement(Node node, String elemNames[]) {
    298
    299         // search for node
    300         Node sibling = node.getNextSibling();
    301         while (sibling != null) {
    302             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
    303                 for (int i = 0; i < elemNames.length; i++) {
    304                     if (sibling.getNodeName().equals(elemNames[i])) {
    305                         return (Element) sibling;
    306                     }
    307                 }
    308             }
    309             sibling = sibling.getNextSibling();
    310         }
    311
    312         // not found
    313         return null;
    314
    315     } // getNextSiblingdElement(Node,String[]):Element
    316
    317     /**
    318      * Finds and returns the first child node with the given qualified name.
    319      */
    320     public static Element getFirstChildElementNS(Node parent,
    321                                                  String[][] elemNames) {
    322
    323         // search for node
    324         Node child = parent.getFirstChild();
    325         while (child != null) {
    326             if (child.getNodeType() == Node.ELEMENT_NODE) {
    327                 for (int i = 0; i < elemNames.length; i++) {
    328                     String uri = child.getNamespaceURI();
    329                     if (uri != null && uri.equals(elemNames[i][0]) &&
    330                             child.getLocalName().equals(elemNames[i][1])) {
    331                         return (Element) child;
    332                     }
    333                 }
    334             }
    335             child = child.getNextSibling();
    336         }
    337
    338         // not found
    339         return null;
    340
    341     } // getFirstChildElementNS(Node,String[][]):Element
    342
    343     /**
    344      * Finds and returns the last child node with the given qualified name.
    345      */
    346     public static Element getLastChildElementNS(Node parent,
    347                                                 String[][] elemNames) {
    348
    349         // search for node
    350         Node child = parent.getLastChild();
    351         while (child != null) {
    352             if (child.getNodeType() == Node.ELEMENT_NODE) {
    353                 for (int i = 0; i < elemNames.length; i++) {
    354                     String uri = child.getNamespaceURI();
    355                     if (uri != null && uri.equals(elemNames[i][0]) &&
    356                             child.getLocalName().equals(elemNames[i][1])) {
    357                         return (Element) child;
    358                     }
    359                 }
    360             }
    361             child = child.getPreviousSibling();
    362         }
    363
    364         // not found
    365         return null;
    366
    367     } // getLastChildElementNS(Node,String[][]):Element
    368
    369     /**
    370      * Finds and returns the next sibling node with the given qualified name.
    371      */
    372     public static Element getNextSiblingElementNS(Node node,
    373                                                   String[][] elemNames) {
    374
    375         // search for node
    376         Node sibling = node.getNextSibling();
    377         while (sibling != null) {
    378             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
    379                 for (int i = 0; i < elemNames.length; i++) {
    380                     String uri = sibling.getNamespaceURI();
    381                     if (uri != null && uri.equals(elemNames[i][0]) &&
    382                             sibling.getLocalName().equals(elemNames[i][1])) {
    383                         return (Element) sibling;
    384                     }
    385                 }
    386             }
    387             sibling = sibling.getNextSibling();
    388         }
    389
    390         // not found
    391         return null;
    392
    393     } // getNextSiblingdElementNS(Node,String[][]):Element
    394
    395     /**
    396      * Finds and returns the first child node with the given name and
    397      * attribute name, value pair.
    398      */
    399     public static Element getFirstChildElement(Node parent,
    400                                                String elemName,
    401                                                String attrName,
    402                                                String attrValue) {
    403
    404         // search for node
    405         Node child = parent.getFirstChild();
    406         while (child != null) {
    407             if (child.getNodeType() == Node.ELEMENT_NODE) {
    408                 Element element = (Element) child;
    409                 if (element.getNodeName().equals(elemName) &&
    410                         element.getAttribute(attrName).equals(attrValue)) {
    411                     return element;
    412                 }
    413             }
    414             child = child.getNextSibling();
    415         }
    416
    417         // not found
    418         return null;
    419
    420     } // getFirstChildElement(Node,String,String,String):Element
    421
    422     /**
    423      * Finds and returns the last child node with the given name and
    424      * attribute name, value pair.
    425      */
    426     public static Element getLastChildElement(Node parent,
    427                                               String elemName,
    428                                               String attrName,
    429                                               String attrValue) {
    430
    431         // search for node
    432         Node child = parent.getLastChild();
    433         while (child != null) {
    434             if (child.getNodeType() == Node.ELEMENT_NODE) {
    435                 Element element = (Element) child;
    436                 if (element.getNodeName().equals(elemName) &&
    437                         element.getAttribute(attrName).equals(attrValue)) {
    438                     return element;
    439                 }
    440             }
    441             child = child.getPreviousSibling();
    442         }
    443
    444         // not found
    445         return null;
    446
    447     } // getLastChildElement(Node,String,String,String):Element
    448
    449     /**
    450      * Finds and returns the next sibling node with the given name and
    451      * attribute name, value pair. Since only elements have attributes,
    452      * the node returned will be of type Node.ELEMENT_NODE.
    453      */
    454     public static Element getNextSiblingElement(Node node,
    455                                                 String elemName,
    456                                                 String attrName,
    457                                                 String attrValue) {
    458
    459         // search for node
    460         Node sibling = node.getNextSibling();
    461         while (sibling != null) {
    462             if (sibling.getNodeType() == Node.ELEMENT_NODE) {
    463                 Element element = (Element) sibling;
    464                 if (element.getNodeName().equals(elemName) &&
    465                         element.getAttribute(attrName).equals(attrValue)) {
    466                     return element;
    467                 }
    468             }
    469             sibling = sibling.getNextSibling();
    470         }
    471
    472         // not found
    473         return null;
    474
    475     } // getNextSiblingElement(Node,String,String,String):Element
    476
    477     /**
    478      * Returns the concatenated child text of the specified node.
    479      * This method only looks at the immediate children of type
    480      * <code>Node.TEXT_NODE</code> or the children of any child
    481      * node that is of type <code>Node.CDATA_SECTION_NODE</code>
    482      * for the concatenation.
    483      *
    484      * @param node The node to look at.
    485      */
    486     public static String getChildText(Node node) {
    487
    488         // is there anything to do?
    489         if (node == null) {
    490             return null;
    491         }
    492
    493         // concatenate children text
    494         StringBuffer str = new StringBuffer();
    495         Node child = node.getFirstChild();
    496         while (child != null) {
    497             short type = child.getNodeType();
    498             if (type == Node.TEXT_NODE) {
    499                 str.append(child.getNodeValue());
    500             } else if (type == Node.CDATA_SECTION_NODE) {
    501                 str.append(getChildText(child));
    502             }
    503             child = child.getNextSibling();
    504         }
    505
    506         // return text value
    507         return str.toString();
    508
    509     } // getChildText(Node):String
    510
    511     // return the name of this element
    512     public static String getName(Node node) {
    513         return node.getNodeName();
    514     } // getLocalName(Element):  String
    515
    516     /**
    517      * returns local name of this element if not null, otherwise
    518      * returns the name of the node
    519      */
    520     public static String getLocalName(Node node) {
    521         String name = node.getLocalName();
    522         return (name != null) ? name : node.getNodeName();
    523     } // getLocalName(Element):  String
    524
    525     public static Element getParent(Element elem) {
    526         Node parent = elem.getParentNode();
    527         if (parent instanceof Element)
    528             return (Element) parent;
    529         return null;
    530     } // getParent(Element):Element
    531
    532     // get the Document of which this Node is a part
    533     public static Document getDocument(Node node) {
    534         return node.getOwnerDocument();
    535     } // getDocument(Node):Document
    536
    537     // return this Document's root node
    538     public static Element getRoot(Document doc) {
    539         return doc.getDocumentElement();
    540     } // getRoot(Document(:  Element
    541
    542     // some methods for handling attributes:
    543
    544     // return the right attribute node
    545     public static Attr getAttr(Element elem, String name) {
    546         return elem.getAttributeNode(name);
    547     } // getAttr(Element, String):Attr
    548
    549     // return the right attribute node
    550     public static Attr getAttrNS(Element elem, String nsUri,
    551                                  String localName) {
    552         return elem.getAttributeNodeNS(nsUri, localName);
    553     } // getAttrNS(Element, String):Attr
    554
    555     // get all the attributes for an Element
    556     public static Attr[] getAttrs(Element elem) {
    557         NamedNodeMap attrMap = elem.getAttributes();
    558         Attr[] attrArray = new Attr[attrMap.getLength()];
    559         for (int i = 0; i < attrMap.getLength(); i++)
    560             attrArray[i] = (Attr) attrMap.item(i);
    561         return attrArray;
    562     } // getAttrs(Element):  Attr[]
    563
    564     // get attribute's value
    565     public static String getValue(Attr attribute) {
    566         return attribute.getValue();
    567     } // getValue(Attr):String
    568
    569     // It is noteworthy that, because of the way the DOM specs
    570     // work, the next two methods return the empty string (not
    571     // null!) when the attribute with the specified name does not
    572     // exist on an element.  Beware!
    573
    574     // return the value of the attribute of the given element
    575     // with the given name
    576     public static String getAttrValue(Element elem, String name) {
    577         return elem.getAttribute(name);
    578     } // getAttr(Element, String):Attr
    579
    580     // return the value of the attribute of the given element
    581     // with the given name
    582     public static String getAttrValueNS(Element elem, String nsUri,
    583                                         String localName) {
    584         return elem.getAttributeNS(nsUri, localName);
    585     } // getAttrValueNS(Element, String):Attr
    586
    587     // return the namespace URI
    588     public static String getNamespaceURI(Node node) {
    589         return node.getNamespaceURI();
    590     }
    591
    592     /**
    593      * Get the input encoding of the document. This uses a DOM 3 API
    594      * call getInputEncoding hence it returns the correct value
    595      * only if a DOM3 API is used. Otherwise it returns the default encoding
    596      * @param doc
    597      * @return the encoding (e.g. UTF-8)
    598      */
    599     public static String getInputEncoding(Document doc) {
    600         try {
    601             Method m = doc.getClass().getMethod("getInputEncoding", new Class[]{});
    602             return (String) m.invoke(doc, new Object[]{});
    603         } catch (Throwable e) {
    604             return DEFAULT_ENCODING;
    605         }
    606     }
    607
    608     /**
    609      * Get the xml encoding of the document. This uses a DOM 3 API
    610      * call getXmlEncoding hence it returns the correct value
    611      * only if a DOM3 API is used. Otherwise it returns the default encoding
    612      * @see #getInputEncoding(Document)
    613      * @param doc
    614      * @return the encoding (e.g. utf-8).
    615      */
    616     public static String getXmlEncoding(Document doc) {
    617         try {
    618         	 Method m = doc.getClass().getMethod("getXmlEncoding", new Class[]{});
    619              return (String) m.invoke(doc, new Object[]{});
    620         } catch (Throwable e) {
    621             return DEFAULT_ENCODING;
    622         }
    623     }
    624 }