2009-04-21 16 views
35

Nie mogę pobrać wartości tekstowej z Node.getNodeValue(), Node.getFirstChild().getNodeValue() lub z Node.getTextContent().Uzyskiwanie wartości tekstowej węzła XML za pomocą Java DOM

Moje XML jest jak

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

I próbuję dostać tag Wartość (nietekstowego elementu ściągam działa poprawnie). Mój kod Java brzmi jak

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

To wypisuje

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

Dzięki za pomoc.

+1

Pomoże ci, jeśli wyraźnie zaznaczysz, co dokładnie oznacza teraz zmienna "n", dokument lub documentElement? – AnthonyWJones

+1

Dodałem część deklaracji "n", część – Emilio

Odpowiedz

45

Wydrukowałem również wynik an2.getNodeName() w celu debugowania. Domyślam się, że twój indeks pełzający drzewo nie indeksuje się do węzłów, które uważasz, że jest. To podejrzenie jest wzmocnione przez brak sprawdzania nazw węzłów w kodzie.

Poza tym javadoc dla węzła definiuje "getNodeValue()", aby zwrócić wartość pustą dla węzłów typu Element. Dlatego naprawdę powinieneś używać getTextContent(). Nie jestem pewien, dlaczego nie dałoby ci tego, czego chcesz.

Być może należy powtórzyć proces potomny węzła znacznika i sprawdzić, jakie typy istnieją?

Próbowałem tego kodu i działa dla mnie:

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

wyjściowy był:

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

. Teraz również drukuję .getNodeName() .. i zwraca odpowiednią wartość (tag). – Emilio

+0

Mój element tagu nie ma elementów childs:/Jeśli spróbuję po prostu z an2. getFirstChild(). getTextContent() lub podobny to throw NullPointerException – Emilio

+0

Spróbuj po prostu użyć getChildElements zamiast getFirstChild(). Być może getFirstChild() przeskakuje nad węzłami typu Element z jakiegoś powodu? – jsight

17

Jeśli XML idzie dość głęboka, warto rozważyć użycie XPath, która pochodzi z JRE , dzięki czemu można uzyskać dostęp do zawartości znacznie łatwiej za pomocą:

Pełny przykład:

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

Niestety jest to zadanie edukacyjne i muszę korzystać z DOM apis:/ – Emilio

+0

Czy możesz korzystać z interfejsu API JDOM? O wiele łatwiej jest z tym pracować. – jdigital

+0

Dzięki, ten kompletny przykład (z importem) naprawdę mi pomógł po zmaganiach z innymi podobnymi rozwiązaniami. –

1

Używam bardzo starej wersji Java. Jdk 1.4.08 i ja mieliśmy ten sam problem. Klasa Node dla mnie nie miała metody getTextContent(). Musiałem użyć Node.getFirstChild().getNodeValue() zamiast Node.getNodeValue(), aby uzyskać wartość węzła. Naprawiono to dla mnie.

1

Jeśli jesteś otwarty na , który wyróżnia się na performance and memory efficiency, poniżej znajduje się kod do wykonywania tego, czego szukasz ... zarówno w XPath, jak i manualnej nawigacji ... ogólny kod jest bardzo zwięzły i łatwiejszy do zrozumienia ...

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)); 
     } 
    } 
} 
Powiązane problemy