2012-07-25 23 views
6

tengo el siguiente archivo xml:Java Dom analizador reporta un número incorrecto de nodos secundarios

<?xml version="1.0" encoding="UTF-8"?> 
<users> 
<user id="0" firstname="John"/> 
</users> 

entonces estoy tratando de analizarlo con Java, pero getChildNodes reporta un número incorrecto de los nodos secundarios.

código Java:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
DocumentBuilder builder = factory.newDocumentBuilder(); 
Document document = builder.parse(this.file); 
document.getDocumentElement().normalize(); 
Element root = document.getDocumentElement(); 
NodeList nodes = root.getChildNodes(); 
System.out.println(nodes.getLength()); 

Resultado: 3

También me estoy haciendo NPE para acceder a los nodos de atributos, así que supongo que algo va muy mal.

Respuesta

3

Hay tres nodos hijo:

  • un nodo de texto que contiene un salto de línea
  • un nodo elemento (usuario etiquetados)
  • un nodo de texto que contiene un salto de línea

Por lo tanto, al procesar los nodos secundarios, verifique los nodos de elemento.

+4

Gracias, ¿conoces una forma de filtrar solo los elementos de forma genérica? –

4

Los nodos secundarios consisten en elementos y nodos de texto para espacios en blanco. Deberá verificar el tipo de nodo antes de procesar los atributos. También es posible que desee considerar el uso de los javax.xml.xpath APIs disponibles en el JDK/JRE comenzando con Java SE 5.

Ejemplo 1

Este ejemplo demuestra cómo emitir una declaración XPath en un DOM.

package forum11649396; 

import java.io.StringReader; 
import javax.xml.parsers.*; 
import javax.xml.xpath.*; 
import org.w3c.dom.*; 
import org.xml.sax.InputSource; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     String xml = "<?xml version='1.0' encoding='UTF-8'?><users><user id='0' firstname='John'/></users>"; 

     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     Document document = db.parse(new InputSource(new StringReader(xml))); 

     XPathFactory xpf = XPathFactory.newInstance(); 
     XPath xpath = xpf.newXPath(); 
     Element userElement = (Element) xpath.evaluate("https://stackoverflow.com/users/user", document, XPathConstants.NODE); 
     System.out.println(userElement.getAttribute("id")); 
     System.out.println(userElement.getAttribute("firstname")); 
    } 

} 

Ejemplo 2

El siguiente ejemplo muestra cómo emite una instrucción XPath contra un InputSource para obtener un nodo DOM. Esto le ahorra tener que analizar XML en un DOM usted mismo.

package forum11649396; 

import java.io.StringReader; 
import javax.xml.xpath.*; 
import org.w3c.dom.*; 
import org.xml.sax.InputSource; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     String xml = "<?xml version='1.0' encoding='UTF-8'?><users><user id='0' firstname='John'/></users>"; 

     XPathFactory xpf = XPathFactory.newInstance(); 
     XPath xpath = xpf.newXPath(); 
     InputSource inputSource = new InputSource(new StringReader(xml)); 
     Element userElement = (Element) xpath.evaluate("https://stackoverflow.com/users/user", inputSource, XPathConstants.NODE); 
     System.out.println(userElement.getAttribute("id")); 
     System.out.println(userElement.getAttribute("firstname")); 
    } 

} 
1

Debe asegurarse de tener en cuenta la '\ n' entre los nodos, que cuentan para los nodos de texto. Puede comprobar que el uso de if(root.getNodeType() == Node.ELEMENT_NODE)

 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder builder = factory.newDocumentBuilder(); 
     Document document = builder.parse(this.file); 
     document.getDocumentElement().normalize(); 
     for(Node root = document.getFirstChild(); root != null; root = root.getNextSibling()) { 
      if(root.getNodeType() == Node.ELEMENT_NODE) { 
       NodeList nodes = root.getChildNodes(); 
       System.out.println(root.getNodeName() + " has "+nodes.getLength()+" children"); 
       for(int i=0; i<nodes.getLength(); i++) { 
        Node n = nodes.item(i); 
        System.out.println("\t"+n.getNodeName()); 
       } 
      } 
     } 
0

No me di cuenta ninguna de las respuestas que abordan su última nota sobre NPE cuando se trata de acceder a los atributos.

También recibo NPE para acceder a los atributos de los nodos, así que supongo que algo va muy mal.

Desde que he visto la siguiente sugerencia en algunos sitios, supongo que es una forma común para acceder a los atributos:

String myPropValue = node.getAttributes().getNamedItem("myProp").getNodeValue(); 

que funciona bien si los nodos siempre contienen un atributo myProp, pero si no tiene atributos, getAttributes devolverá nulo.Además, si hay atributos, pero no tiene el atributo myProp, getNamedItem devolverá nulo.

actualmente estoy usando

public static String getStrAttr(Node node, String key) { 
    if (node.hasAttributes()) { 
     Node item = node.getAttributes().getNamedItem(key); 
     if (item != null) { 
      return item.getNodeValue(); 
     } 
    } 

    return null; 
} 

public static int getIntAttr(Node node, String key) { 
    if (node.hasAttributes()) { 
     Node item = node.getAttributes().getNamedItem(key); 
     if (item != null) { 
      return Integer.parseInt(item.getNodeValue()); 
     } 
    } 

    return -1; 
} 

en una clase de utilidad, pero su experiencia puede variar.

Cuestiones relacionadas