Cómo leer XML usando XPath en Java

Quiero leer datos XML usando XPath en Java, por lo que para la información que he reunido no puedo analizar XML de acuerdo con mis requisitos.

esto es lo que quiero hacer:

Obtenga el archivo XML en línea a través de su URL, luego use XPath para analizarlo, quiero crear dos métodos en él. Una es en la que ingreso un id. De atributo de nodo específico, y obtengo todos los nodos secundarios como resultado, y el segundo es supongo que solo quiero obtener un valor específico de nodo hijo

   http://www.rgagnonjavahowto.htm taxi   http://www.rgagnon/pbhowto.htm http://www.rgagnon/pbhowtonew.htm   http://www.rgagnon/jshowto.htm   http://www.rgagnon/vbshowto.htm   

En el ejemplo anterior quiero leer todos los elementos si busco a través de @name y también una función en la que solo quiero que la URL de @name ‘Javascript’ solo devuelva un elemento de nodo.

Espero haber aclarado mi pregunta 🙂

Gracias.

Kai

Necesitas algo similar a esto:

 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(); XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); XPathExpression expr = xpath.compile(); 

A continuación, llama a expr.evaluate() pasando el documento definido en ese código y el tipo de devolución que está esperando, y emite el resultado al tipo de objeto del resultado.

Si necesita ayuda con una expresión XPath específica, probablemente debería formularla como preguntas separadas (a menos que esa sea su pregunta en primer lugar, entendí que su pregunta era cómo usar la API en Java).

Editar: (Respuesta al comentario): esta expresión XPath le mostrará el texto del primer elemento URL bajo PowerBuilder:

 /howto/topic[@name='PowerBuilder']/url/text() 

Esto te dará el segundo:

 /howto/topic[@name='PowerBuilder']/url[2]/text() 

Lo entiendes con este código:

 expr.evaluate(doc, XPathConstants.STRING); 

Si no sabe cuántas URL hay en un nodo determinado, entonces debería hacer algo como esto:

 XPathExpression expr = xpath.compile("/howto/topic[@name='PowerBuilder']/url"); NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); 

Y luego recorra el NodeList.

Puedes probar esto.

Documento XML

Guardar como employees.xml .

 < ?xml version="1.0" encoding="UTF-8"?>   29 Pankaj Male Java Developer   35 Lisa Female CEO   40 Tom Male Manager   25 Meghan Female Manager   

Clase de analizador

La clase tiene los siguientes métodos

  • Artículo de lista
  • Un método que devolverá el nombre del empleado para la identificación de entrada.
  • Un método que devolverá la lista del nombre de los empleados con una antigüedad superior a la edad de entrada.
  • Un método que devolverá la lista del nombre de las empleadas.

Código fuente

 import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class Parser { public static void main(String[] args) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder; Document doc = null; try { builder = factory.newDocumentBuilder(); doc = builder.parse("employees.xml"); // Create XPathFactory object XPathFactory xpathFactory = XPathFactory.newInstance(); // Create XPath object XPath xpath = xpathFactory.newXPath(); String name = getEmployeeNameById(doc, xpath, 4); System.out.println("Employee Name with ID 4: " + name); List names = getEmployeeNameWithAge(doc, xpath, 30); System.out.println("Employees with 'age>30' are:" + Arrays.toString(names.toArray())); List femaleEmps = getFemaleEmployeesName(doc, xpath); System.out.println("Female Employees names are:" + Arrays.toString(femaleEmps.toArray())); } catch (ParserConfigurationException | SAXException | IOException e) { e.printStackTrace(); } } private static List getFemaleEmployeesName(Document doc, XPath xpath) { List list = new ArrayList<>(); try { //create XPathExpression object XPathExpression expr = xpath.compile("/Employees/Employee[gender='Female']/name/text()"); //evaluate expression result on XML document NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < nodes.getLength(); i++) list.add(nodes.item(i).getNodeValue()); } catch (XPathExpressionException e) { e.printStackTrace(); } return list; } private static List getEmployeeNameWithAge(Document doc, XPath xpath, int age) { List list = new ArrayList<>(); try { XPathExpression expr = xpath.compile("/Employees/Employee[age>" + age + "]/name/text()"); NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); for (int i = 0; i < nodes.getLength(); i++) list.add(nodes.item(i).getNodeValue()); } catch (XPathExpressionException e) { e.printStackTrace(); } return list; } private static String getEmployeeNameById(Document doc, XPath xpath, int id) { String name = null; try { XPathExpression expr = xpath.compile("/Employees/Employee[@id='" + id + "']/name/text()"); name = (String) expr.evaluate(doc, XPathConstants.STRING); } catch (XPathExpressionException e) { e.printStackTrace(); } return name; } } 

Primeros pasos ejemplo:

archivo xml:

   Snow Crash Neal Stephenson Spectra 0553380958 14.95   Burning Tower Larry Niven Jerry Pournelle Pocket 0743416910 5.99   Zodiac Neal Stephenson Spectra 0553573862 7.50    

Código Java:

 import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; try { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document doc = docBuilder.parse (new File("c:\\tmp\\my.xml")); // normalize text representation doc.getDocumentElement().normalize(); System.out.println ("Root element of the doc is " + doc.getDocumentElement().getNodeName()); NodeList listOfBooks = doc.getElementsByTagName("book"); int totalBooks = listOfBooks.getLength(); System.out.println("Total no of books : " + totalBooks); for(int i=0; i 

Aquí hay un ejemplo de procesamiento de xpath con vtd-xml … para procesamiento XML de alta resistencia es insuperable. aquí está el documento reciente sobre este tema Processing XML with Java – A Performance Benchmark

 import com.ximpleware.*; public class changeAttrVal { public static void main(String s[]) throws VTDException,java.io.UnsupportedEncodingException,java.io.IOException{ VTDGen vg = new VTDGen(); if (!vg.parseFile("input.xml", false)) return; VTDNav vn = vg.getNav(); AutoPilot ap = new AutoPilot(vn); XMLModifier xm = new XMLModifier(vn); ap.selectXPath("/*/place[@id=\"p14\" and @initialMarking=\"2\"]/@initialMarking"); int i=0; while((i=ap.evalXPath())!=-1){ xm.updateToken(i+1, "499");// change initial marking from 2 to 499 } xm.output("new.xml"); } } 

Ampliando la excelente respuesta de @bluish y @Yishai, aquí es cómo usted hace que las NodeLists y los atributos de nodo apoyen los iteradores, es decir, la interfaz for(Node n: nodelist) .

Úselo como:

 NodeList nl = ... for(Node n : XmlUtil.asList(nl)) {...} 

y

 Node n = ... for(Node attr : XmlUtil.asList(n.getAttributes()) {...} 

El código:

 /** * Converts NodeList to an iterable construct. * From: https://stackoverflow.com/a/19591302/779521 */ public final class XmlUtil { private XmlUtil() {} public static List asList(NodeList n) { return n.getLength() == 0 ? Collections.emptyList() : new NodeListWrapper(n); } static final class NodeListWrapper extends AbstractList implements RandomAccess { private final NodeList list; NodeListWrapper(NodeList l) { this.list = l; } public Node get(int index) { return this.list.item(index); } public int size() { return this.list.getLength(); } } public static List asList(NamedNodeMap n) { return n.getLength() == 0 ? Collections.emptyList() : new NodeMapWrapper(n); } static final class NodeMapWrapper extends AbstractList implements RandomAccess { private final NamedNodeMap list; NodeMapWrapper(NamedNodeMap l) { this.list = l; } public Node get(int index) { return this.list.item(index); } public int size() { return this.list.getLength(); } } } 

Lea el archivo XML usando XPathFactory, SAXParserFactory y StAX (JSR-173) .

Usando XPath get node y sus datos secundarios.

 public static void main(String[] args) { String xml = "" + "" + "JavaJavascriptSelenium" + "javascriptYash-777" + ""; String jsonNameSpaces = "{'soapenv':'http://schemas.xmlsoap.org/soap/envelope/'," + "'Yash':'http://Yash.stackoverflow.com/Services/Yash'}"; String xpathExpression = "//Yash:Data"; Document doc1 = getDocument(false, "fileName", xml); getNodesFromXpath(doc1, xpathExpression, jsonNameSpaces); System.out.println("\n===== ***** ====="); Document doc2 = getDocument(true, "./books.xml", xml); getNodesFromXpath(doc2, "//person", "{}"); } static Document getDocument( boolean isFileName, String fileName, String xml ) { Document doc = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(false); factory.setNamespaceAware(true); factory.setIgnoringComments(true); factory.setIgnoringElementContentWhitespace(true); DocumentBuilder builder = factory.newDocumentBuilder(); if( isFileName ) { File file = new File( fileName ); FileInputStream stream = new FileInputStream( file ); doc = builder.parse( stream ); } else { doc = builder.parse( string2Source( xml ) ); } } catch (SAXException | IOException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } return doc; } /** * ELEMENT_NODE[1],ATTRIBUTE_NODE[2],TEXT_NODE[3],CDATA_SECTION_NODE[4], * ENTITY_REFERENCE_NODE[5],ENTITY_NODE[6],PROCESSING_INSTRUCTION_NODE[7], * COMMENT_NODE[8],DOCUMENT_NODE[9],DOCUMENT_TYPE_NODE[10],DOCUMENT_FRAGMENT_NODE[11],NOTATION_NODE[12] */ public static void getNodesFromXpath( Document doc, String xpathExpression, String jsonNameSpaces ) { try { XPathFactory xpf = XPathFactory.newInstance(); XPath xpath = xpf.newXPath(); JSONObject namespaces = getJSONObjectNameSpaces(jsonNameSpaces); if ( namespaces.size() > 0 ) { NamespaceContextImpl nsContext = new NamespaceContextImpl(); Iterator< ?> key = namespaces.keySet().iterator(); while (key.hasNext()) { // Apache WebServices Common Utilities String pPrefix = key.next().toString(); String pURI = namespaces.get(pPrefix).toString(); nsContext.startPrefixMapping(pPrefix, pURI); } xpath.setNamespaceContext(nsContext ); } XPathExpression compile = xpath.compile(xpathExpression); NodeList nodeList = (NodeList) compile.evaluate(doc, XPathConstants.NODESET); displayNodeList(nodeList); } catch (XPathExpressionException e) { e.printStackTrace(); } } static void displayNodeList( NodeList nodeList ) { for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); String NodeName = node.getNodeName(); NodeList childNodes = node.getChildNodes(); if ( childNodes.getLength() > 1 ) { for (int j = 0; j < childNodes.getLength(); j++) { Node child = childNodes.item(j); short nodeType = child.getNodeType(); if ( nodeType == 1 ) { System.out.format( "\n\t Node Name:[%s], Text[%s] ", child.getNodeName(), child.getTextContent() ); } } } else { System.out.format( "\n Node Name:[%s], Text[%s] ", NodeName, node.getTextContent() ); } } } static InputSource string2Source( String str ) { InputSource inputSource = new InputSource( new StringReader( str ) ); return inputSource; } static JSONObject getJSONObjectNameSpaces( String jsonNameSpaces ) { if(jsonNameSpaces.indexOf("'") > -1) jsonNameSpaces = jsonNameSpaces.replace("'", "\""); JSONParser parser = new JSONParser(); JSONObject namespaces = null; try { namespaces = (JSONObject) parser.parse(jsonNameSpaces); } catch (ParseException e) { e.printStackTrace(); } return namespaces; } 

Documento XML

 < ?xml version="1.0" encoding="UTF-8"?>   Yash M 22   Bill Gates 46   Steve Jobs 40   

Fuera puesto para el XPathExpression dado:

 String xpathExpression = "//person/first"; /*OutPut: Node Name:[first], Text[Yash] Node Name:[first], Text[Bill] Node Name:[first], Text[Steve] */ String xpathExpression = "//person"; /*OutPut: Node Name:[first], Text[Yash] Node Name:[last], Text[M] Node Name:[age], Text[22] Node Name:[first], Text[Bill] Node Name:[last], Text[Gates] Node Name:[age], Text[46] Node Name:[first], Text[Steve] Node Name:[last], Text[Jobs] Node Name:[age], Text[40] */ String xpathExpression = "//Yash:Data"; /*OutPut: Node Name:[Yash:Tags], Text[Java] Node Name:[Yash:Tags], Text[Javascript] Node Name:[Yash:Tags], Text[Selenium] Node Name:[Yash:Top], Text[javascript] Node Name:[Yash:User], Text[Yash-777] */ 

Vea este enlace para nuestra propia Implementación de NamespaceContext