使用 Java DOM 获取 XML 节点文本值

2022-09-01 01:57:11

我无法获取带有 的文本值,或者使用 .Node.getNodeValue()Node.getFirstChild().getNodeValue()Node.getTextContent()

我的 XML 就像

<add job="351">
    <tag>foobar</tag>
    <tag>foobar2</tag>
</add>

我正在尝试获取标记值(非文本元素提取工作正常)。我的 Java 代码听起来像

Document doc = db.parse(new File(args[0]));
Node n = doc.getFirstChild();
NodeList nl = n.getChildNodes();   
Node an,an2;

for (int i=0; i < nl.getLength(); i++) {
    an = nl.item(i);

    if(an.getNodeType()==Node.ELEMENT_NODE) {
        NodeList nl2 = an.getChildNodes();

        for(int i2=0; i2<nl2.getLength(); i2++) {
            an2 = nl2.item(i2);

            // DEBUG PRINTS
            System.out.println(an2.getNodeName() + ": type (" + an2.getNodeType() + "):");

            if(an2.hasChildNodes())
                System.out.println(an2.getFirstChild().getTextContent());

            if(an2.hasChildNodes())
                System.out.println(an2.getFirstChild().getNodeValue());

            System.out.println(an2.getTextContent());
            System.out.println(an2.getNodeValue());
        }
    }
}

它打印出来

tag type (1): 
tag1
tag1
tag1
null
#text type (3):
_blank line_
_blank line_
...

感谢您的帮助。


答案 1

我也会打印出的结果,以便进行调试。我的猜测是,您的树爬网代码不会爬行到您认为的节点。由于代码中缺少对节点名称的检查,这种怀疑会加剧。an2.getNodeName()

除此之外,Node的javadoc定义了“getNodeValue()”来为元素类型的节点返回null。因此,你真的应该使用getTextContent()。我不确定为什么这不会给你你想要的文本。

也许迭代标签节点的子节点,看看有什么类型?

尝试了此代码,它适用于我:

String xml = "<add job=\"351\">\n" +
             "    <tag>foobar</tag>\n" +
             "    <tag>foobar2</tag>\n" +
             "</add>";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
ByteArrayInputStream bis = new ByteArrayInputStream(xml.getBytes());
Document doc = db.parse(bis);
Node n = doc.getFirstChild();
NodeList nl = n.getChildNodes();
Node an,an2;

for (int i=0; i < nl.getLength(); i++) {
    an = nl.item(i);
    if(an.getNodeType()==Node.ELEMENT_NODE) {
        NodeList nl2 = an.getChildNodes();

        for(int i2=0; i2<nl2.getLength(); i2++) {
            an2 = nl2.item(i2);
            // DEBUG PRINTS
            System.out.println(an2.getNodeName() + ": type (" + an2.getNodeType() + "):");
            if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getTextContent());
            if(an2.hasChildNodes()) System.out.println(an2.getFirstChild().getNodeValue());
            System.out.println(an2.getTextContent());
            System.out.println(an2.getNodeValue());
        }
    }
}

输出为:

#text: type (3): foobar foobar
#text: type (3): foobar2 foobar2

答案 2

如果您的 XML 非常深入,您可能需要考虑使用 JRE 附带的 XPath,以便您可以更轻松地使用以下内容访问内容:

String text = xp.evaluate("//add[@job='351']/tag[position()=1]/text()", 
    document.getDocumentElement());

完整示例:

import static org.junit.Assert.assertEquals;
import java.io.StringReader;    
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;    
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

public class XPathTest {

    private Document document;

    @Before
    public void setup() throws Exception {
        String xml = "<add job=\"351\"><tag>foobar</tag><tag>foobar2</tag></add>";
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        document = db.parse(new InputSource(new StringReader(xml)));
    }

    @Test
    public void testXPath() throws Exception {
        XPathFactory xpf = XPathFactory.newInstance();
        XPath xp = xpf.newXPath();
        String text = xp.evaluate("//add[@job='351']/tag[position()=1]/text()",
                document.getDocumentElement());
        assertEquals("foobar", text);
    }
}