代码之家  ›  专栏  ›  技术社区  ›  anjanb

最佳Java XML解析器操作/编辑现有XML文档

  •  6
  • anjanb  · 技术社区  · 15 年前

    任务:我有一个使用xml名称空间和xml模式的现有xml文档(utf-8)。我需要解析到一个特定的元素,将内容(也需要使用xml名称空间前缀)附加到这个元素,然后再次写出文档。

    对于这个任务,我应该使用哪一个XML解析器库最好?

    我以前看过一条线索( Best XML parser for Java )但不确定dom4j或jdom是否适合namespaces/xmlschema和对utf-8字符的良好支持。

    有些解析器似乎是
    JDOM
    多姆J
    XOM
    伍德斯托克

    知道哪一个最好吗?:-)我使用JDK6,不希望使用内置的SAX/DOM工具来完成这项工作,因为这需要我编写太多代码。

    有一些这样做的例子会有帮助。

    4 回复  |  直到 13 年前
        1
  •  5
  •   Dean J    15 年前

    使用jdom,获取inputstream并使其成为文档:

    InputStream inputStream = (InputStream)httpURLConnection.getContent();
    DocumentBuilderFactory docbf = DocumentBuilderFactory.newInstance();
    docbf.setNamespaceAware(true);
    DocumentBuilder docbuilder = docbf.newDocumentBuilder();
    Document document = docbuilder.parse(inputStream, baseUrl);
    

    在那一点上,Java对象中有XML。完成。容易的。

    您可以使用文档对象和Java API来遍历它,也可以使用XPath,我发现它更容易(一旦我学会了它)。

    构建一个xpath对象,这需要一点:

    public static XPath buildXPath() {
        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        xpath.setNamespaceContext(new AtomNamespaceContext());
        return xpath;
    }
    
    
    public class AtomNamespaceContext implements NamespaceContext {
    
        public String getNamespaceURI(String prefix) {
            if (prefix == null)
                throw new NullPointerException("Null prefix");
            else if ("a".equals(prefix))
                return "http://www.w3.org/2005/Atom";
            else if ("app".equals(prefix))
                return "http://www.w3.org/2007/app";
            else if ("os".equals(prefix))
                return "http://a9.com/-/spec/opensearch/1.1/";
            else if ("x".equals(prefix)) 
                return "http://www.w3.org/1999/xhtml";
            else if ("xml".equals(prefix))
                return XMLConstants.XML_NS_URI;
            return XMLConstants.NULL_NS_URI;
        }
    
        // This method isn't necessary for XPath processing.
        public String getPrefix(String uri) {
            throw new UnsupportedOperationException();
        }
    
        // This method isn't necessary for XPath processing either.
        public Iterator getPrefixes(String uri) {
            throw new UnsupportedOperationException();
        }
    }
    

    那就用它吧,它(谢天谢地)根本不需要花太多时间:

    return Integer.parseInt(xpath.evaluate("/a:feed/os:totalResults/text()", document));
    
        2
  •  6
  •   Russell Leggett    15 年前

    使用XSLT。说真的。这是一个完美的工作。只需使用一个复制模板复制所有内容,除了需要添加更多xml的地方。甚至可以通过实际编写xml而不是dom操作来添加xml。

    这是复制模板:

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    

    我知道很多人都讨厌xslt,但这是一项非常出色的任务,几乎不需要任何代码。另外,您可以使用jdk中的内容。

        3
  •  2
  •   Lukas Eder    13 年前

    由于编写太多代码是您的主要问题,您可能需要考虑joox:

    http://code.google.com/p/joox/

    我创建了Joox成为JQuery到Java的一个端口。底层技术是Java的标准DOM。一些示例代码:

    // Find the order at index for and add an element "paid"
    $(document).find("orders").children().eq(4)
               .append("<paid>true</paid>");
    
    // Find those orders that are paid and flag them as "settled"
    $(document).find("orders").children().find("paid")
               .after("<settled>true</settled>");
    
    // Add a complex element
    $(document).find("orders").append(
      $("order", $("date", "2011-08-14"),
                 $("amount", "155"),
                 $("paid", "false"),
                 $("settled", "false")).attr("id", "13");
    

    注意:名称空间还没有明确支持,但是您可以解决这个问题

        4
  •  1
  •   Kevin    15 年前

    听起来你可以写一个xslt样式表来做你想做的事情。