【问题标题】:How to parse the full content of a XML Tag in java如何在java中解析XML标签的全部内容
【发布时间】:2020-05-19 11:44:30
【问题描述】:

我有某种复杂的 XML 数据结构。该结构包含不同的片段,如下例所示:

<data>
  <content-part-1>
   <h1>Hello <strong>World</strong>. This is some text.</h1>
   <h2>.....</h2>
  </content-part1>
  ....
</data>

标签“content-part-1”中的 h1 标签很有趣。我想获取 xml 标签“h1”的全部内容。

在 java 中,我使用了 javax.xml.parsers.DocumentBuilder 并尝试了类似的方法:

String my_content="<h1>Hello <strong>World</strong>. This is some text.</h1>"; 
// parse h1 tag..
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = documentBuilder.parse(new InputSource(new StringReader(my_content)));
Node node = doc.importNode(doc.getDocumentElement(), true);
if (node != null && node.getNodeName().equals("h1")) {
    return node.getTextContent();
}

但是方法 'getTextContent()' 会返回:

Hello World. This is some text.

xml 解析器删除标签“strong”(因为它是记录在案的行为)。

我的问题是如何在不进一步解析节点内容的情况下提取 org.w3c.dom.Document 中单个 XML 节点的全部内容?

【问题讨论】:

  • 这是一个非常不寻常的要求。请编辑问题并解释为什么您认为这是一件有用的事情。
  • 我编辑我的问题。我不认为这个要求是如此奇特。但也许 javax.xml.parsers.DocumentBuilder 方法是错误的。使用正则表达式手动解析 XML 片段似乎更容易......

标签: java xml xml-parsing


【解决方案1】:

虽然 java DOM 解析器提供了解析混合内容的功能,但在这种特殊情况下,使用 Jsoup 库可能更方便。使用它提取h1元素内容的代码如下:

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

String text = "<data>\n"
+ "  <content-part1>\n"
+ "   <h1>Hello <strong>World</strong>. This is some text.</h1>\n"
+ "   <h2></h2>\n"
+ "  </content-part1>\n"
+ "</data>";

Document doc = Jsoup.parse(text);

Elements h1Elements = doc.select("h1");

for (Element h1 : h1Elements) {
    System.out.println(h1.html());
}

这种情况下的输出将是“Hello &lt;strong&gt;World&lt;/strong&gt;. This is some text.

【讨论】:

  • 请确保向 Jsoup 指定要使用 XML 解析器。否则它将默认为 HTML,并且由于树解析器,您可能会得到意想不到的结果。 Jsoup.parse(html, "", Parser.xmlParser());
【解决方案2】:

您可能想要的是从文档的某个子节点生成 XML。 所以稍微修改nodeToString from earlier answer to similar question我可以建议 生成文本&lt;h1&gt;Hello &lt;strong&gt;World&lt;/strong&gt;. This is some text.&lt;/h1&gt;。摆脱&lt;h1&gt;&lt;/h1&gt; 可能需要一些额外的努力

package com.github.vtitov.test;

import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import java.io.StringReader;
import java.io.StringWriter;

import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;


public class XmlTest {

    @Test
    public void buildXml() throws Exception {
        String my_content="<h1>Hello <strong>World</strong>. This is some text.</h1>";
        // parse h1 tag..
        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = documentBuilder.parse(new InputSource(new StringReader(my_content)));
        Node node = doc.importNode(doc.getDocumentElement(), true);
        String h1Content = null;
        if (node != null && node.getNodeName().equals("h1")) {
            h1Content = nodeToString(node);
        }
        assertThat("h1", h1Content, equalTo("<h1>Hello <strong>World</strong>. This is some text.</h1>"));
    }

    private static String nodeToString(Node node) throws TransformerException {
        StringWriter sw = new StringWriter();
        Transformer t = TransformerFactory.newInstance().newTransformer();
        t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        t.setOutputProperty(OutputKeys.INDENT, "no");
        t.transform(new DOMSource(node), new StreamResult(sw));
        return sw.toString();
    }
}

【讨论】:

  • 这已接近解决方案。但现在我需要一种方法来删除 h1 标签。似乎使用 DocumentBuilder 通常是错误的方法。
  • 我认为 DOM 模型在这里不合适,因为您想从 xml 创建非 xml。可能值得使用 SAX 或 StAX。
  • 我认为您的方法可能是错误的。您应该解析 HTML,修改生成的 DOM 树,然后将修改后的 DOM 树序列化为 HTML。我知道并不是所有的 HTML 都是有效的 XML,但是 parse-modify-serialize 是要走的路。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多