web-dev-qa-db-ja.com

Node DOMを使用したXML Java text値の取得

Node.getNodeValue()Node.getFirstChild().getNodeValue()、またはNode.getTextContent()でテキスト値を取得できません。

私のXMLは

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

そして、私はtag valueを取得しようとしています(非テキスト要素のフェッチは正常に機能します)。私の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_
...

助けてくれてありがとう。

37
Emilio

an2.getNodeName()の結果もデバッグ目的で出力します。私の推測では、ツリーのクロールコードは、あなたが考えているノードにクロールされていません。この疑いは、コード内のノード名のチェックの欠如によって強化されます。

それ以外では、Node=のjavadocは、「 getNodeValue ()」を定義して、Element型のノードに対して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
49
jsight

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);
    }
}
18
toolkit

非常に古いJavaを使用しています。 Jdk 1.4.08と同じ問題がありました。 NodeクラスにはgetTextContent()メソッドがありませんでした。ノードの値を取得するには、Node.getFirstChild().getNodeValue()の代わりにNode.getNodeValue()を使用する必要がありました。これは私のために修正されました。

3
Zeus

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));
        }
    }
}
1
vtd-xml-author