2009-04-21 8 views
35

Node.getNodeValue(), Node.getFirstChild().getNodeValue() 또는 Node.getTextContent()을 사용하여 텍스트 값을 가져올 수 없습니다.Java DOM을 사용하여 XML 노드 텍스트 값 가져 오기

내 XML은

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

처럼 그리고 태그 값 (미세 작품을 가져 오는 텍스트가 아닌 요소)를 얻기 위해 노력하고있어. 그것은 도움을

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

감사를 출력

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()); 
     } 
    } 
} 

처럼 내 자바 코드가 들린다.

+1

변수 'n'이 현재 정확하게 보유하고있는 Document 또는 documentElement를 명확하게 나타내면 도움이 될 것입니다. – AnthonyWJones

+1

'n'선언 부분을 추가했습니다. – Emilio

답변

45

디버깅 목적으로 an2.getNodeName()의 결과도 인쇄합니다. 내 생각 엔 나무 크롤링 코드가 생각하는 노드에 크롤링하지 않는 것입니다. 그 의심은 코드에서 노드 이름을 확인하지 않아서 향상됩니다.

노드 외의 경우 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()); 
     } 
    } 
} 

출력했다 :

당신의 XML은 매우 깊은된다면
#text: type (3): foobar foobar 
#text: type (3): foobar2 foobar2 
+1

.getNodeName() .. 이제 올바른 값 (태그)을 반환합니다. – Emilio

+0

내 태그 요소에 하위 항목이 없습니다./단순히 an2로 시도하면. getFirstChild(). getTextContent() 또는 비슷하게 NullPointerException을 throw합니다. – Emilio

+0

getFirstChild() 대신 getChildElements를 사용해보십시오. 아마도 getFirstChild()가 어떤 이유로 엘리먼트 형 노드를 건너 뛰는 것일까? – jsight

17

, 당신은 당신의 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); 
    } 
} 
+0

불행히도 교육적인 직업이며 나는 DOM apis를 사용해야합니다 :/ – Emilio

+0

JDOM API를 사용할 수 있습니까? 함께 일하는 것이 훨씬 쉽습니다. – jdigital

+0

감사합니다.이 비슷한 예제 (수입품 포함)는 다른 유사한 솔루션으로 고생하면서 정말로 도움이되었습니다. –

1

저는 아주 오래된 자바를 사용합니다. JDK 1.4.08과 같은 문제가있었습니다. 나를위한 Node 클래스에는 getTextContent() 메소드가 없었습니다. 노드의 값을 얻으려면 Node.getNodeValue() 대신 Node.getFirstChild().getNodeValue()을 사용해야했습니다. 이것은 나를 위해 고정.

1

모두 performance and memory efficiency에능한 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)); 
     } 
    } 
} 
관련 문제