Получение текстового значения узла XML с помощью Java DOM - PullRequest
37 голосов
/ 21 апреля 2009

Я не могу получить текстовое значение с Node.getNodeValue(), Node.getFirstChild().getNodeValue() или с Node.getTextContent().

Мой XML похож на

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

И я пытаюсь получить значение tag (нетекстовая выборка элементов работает нормально). Мой код 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_
...

Спасибо за помощь.

Ответы [ 4 ]

48 голосов
/ 21 апреля 2009

Я бы распечатал результат an2.getNodeName() также для целей отладки. Я предполагаю, что ваш код обхода дерева не сканирует те узлы, о которых вы думаете. Это подозрение усиливается отсутствием проверки имен узлов в вашем коде.

Кроме этого, javadoc для Node определяет " getNodeValue ()", чтобы возвратить ноль для узлов типа Element. Следовательно, вы действительно должны использовать 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
18 голосов
/ 21 апреля 2009

Если ваш XML идет достаточно глубоко, вы можете рассмотреть возможность использования XPath, который поставляется вместе с вашей JRE, так что вы можете получить гораздо более легкий доступ к содержимому, используя:

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);
    }
}
2 голосов
/ 18 февраля 2015

Я использую очень старую Java. JDK 1.4.08 и у меня была такая же проблема. В классе Node для меня не было метода getTextContent(). Мне пришлось использовать Node.getFirstChild().getNodeValue() вместо Node.getNodeValue(), чтобы получить значение узла. Это исправлено для меня.

1 голос
/ 24 апреля 2016

Если вы открыты для vtd-xml , который отличается как по производительности, так и по эффективности памяти , ниже приведен код для выполнения того, что вы ищете ... в обоих XPath и ручная навигация ... общий код гораздо лаконичнее и проще для понимания ...

import com.ximpleware.*;
public class queryText {
    public static void main(String[] s) throws VTDException{
        VTDGen vg = new VTDGen();
        if (!vg.parseFile("input.xml", true))
            return;
        VTDNav vn = vg.getNav();
        AutoPilot ap = new AutoPilot(vn);
        // first manually navigate
        if(vn.toElement(VTDNav.FC,"tag")){
            int i= vn.getText();
            if (i!=-1){
                System.out.println("text ===>"+vn.toString(i));
            }
            if (vn.toElement(VTDNav.NS,"tag")){
                i=vn.getText();
                System.out.println("text ===>"+vn.toString(i));
            }
        }

        // second version use XPath
        ap.selectXPath("/add/tag/text()");
        int i=0;
        while((i=ap.evalXPath())!= -1){
            System.out.println("text node ====>"+vn.toString(i));
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...