2009-04-21 14 views
35

No puedo recuperar el valor del texto con Node.getNodeValue(), Node.getFirstChild().getNodeValue() o con Node.getTextContent().Obtención del valor del texto del nodo XML con Java DOM

Mi XML es como

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

y estoy tratando de conseguir etiqueta de valor (elemento no textual ir a buscar funciona bien). Mi código Java suena como

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

Se imprime

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

Gracias por la ayuda.

+1

Ayudaría si indicara claramente qué contiene exactamente la variable 'n', el documento o el elemento del documento? – AnthonyWJones

+1

he agregado la parte de declaración 'n' – Emilio

Respuesta

45

Imprimía el resultado de an2.getNodeName() también para depuración. Supongo que el código de rastreo de tu árbol no se está arrastrando a los nodos que crees que es. Esa sospecha se ve reforzada por la falta de comprobación de los nombres de nodo en su código.

Aparte de eso, el javadoc para el nodo define "getNodeValue()" para devolver nulo para los nodos de tipo Elemento. Por lo tanto, realmente debería usar getTextContent(). No estoy seguro de por qué eso no le daría el texto que desea.

¿Quizás repetir los elementos secundarios de su nodo de etiqueta y ver qué tipos hay?

probado este código y que funciona para mí:

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

salida fue:

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

ahora estoy imprimiendo también .getNodeName() .. y devuelve el valor correcto (etiqueta) – Emilio

+0

Mi elemento de etiqueta no tiene hijos:/Si lo intento simplemente con an2. getFirstChild(). getTextContent() o similar arroja una NullPointerException – Emilio

+0

Intenta simplemente usar getChildElements en lugar de getFirstChild(). Quizás getFirstChild() omita nodos escritos por Element por alguna razón? – jsight

17

Si el código XML va bastante profundo, es posible que desee considerar el uso de XPath, que viene con el JRE , para que pueda acceder a los contenidos mucho más fácil usando:

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

ejemplo completo:

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

Desafortunadamente es un trabajo educativo y debo usar DOM apis:/ – Emilio

+0

¿Se puede usar la API de JDOM? Es mucho más fácil trabajar con él. – jdigital

+0

Gracias, este ejemplo completo (con importaciones) realmente me ayudó después de luchar con otras soluciones similares. –

1

Utilizo un Java muy antiguo. Jdk 1.4.08 y yo tuvimos el mismo problema. La clase Node para mí no tenía el método getTextContent(). Tuve que usar Node.getFirstChild().getNodeValue() en lugar de Node.getNodeValue() para obtener el valor del nodo. Esto arreglado para mí.

1

Si está abierto a vtd-xml, que se destaca en ambos performance and memory efficiency, a continuación se muestra el código para hacer lo que está buscando ... tanto en navegación manual como en XPath ... el código general es mucho más conciso y fácil de entender ...

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)); 
     } 
    } 
} 
Cuestiones relacionadas