3

I have XML file parsed by XPath to get all the parameters in it, and then i want to get the full path to each parameter but my code didn't work for some reason. The Code:

ArrayList<String> names = new ArrayList<String>();
ArrayList<String> paths = new ArrayList<String>();
URL oracle = new URL("http://weather.yahooapis.com/forecastrss?w=2502265");
InputStream is = oracle.openStream();
org.w3c.dom.Document doc = null;
DocumentBuilderFactory domFactory;
DocumentBuilder builder;
try {
    domFactory = DocumentBuilderFactory.newInstance();
    domFactory.setNamespaceAware(true);
    builder = domFactory.newDocumentBuilder();
    doc = builder.parse(is);
} catch (Exception ex) {
    System.err.println("unable to load XML: " + ex);
}

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("//*/@*");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nl = (NodeList) result;
for(int j=0 ; j < nl.getLength() ; j++){
    names.add(nl.item(j).getNodeName());
    Node node = nl.item(j);
    ArrayList<String> parents = new ArrayList<String>();
    while(node.getParentNode() != null){ // it didn't even gone through this loop
        parents.add(node.getNodeName());
        node = node.getParentNode();
    }
    System.out.println(parents);
}       
Muhammed Refaat
  • 8,914
  • 14
  • 83
  • 118
  • If you're fine with XPath 2.0, I proposed an expression building those pathes in an answer on another question: http://stackoverflow.com/a/16491186/695343 - it will work fine for all atributes, too; returning a list of XPath expressions with a path for each attribute. – Jens Erat May 19 '13 at 12:13

1 Answers1

2

The expression //*/@* returns an empty NodeSet.

The code below retrieve the paths you need:

import org.w3c.dom.Attr;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class SO {

   @SuppressWarnings("nls")
   public static void main( String[] args ) throws Exception {
      List< String > names = new ArrayList<>();
      URL oracle =
         new URL( "http://weather.yahooapis.com/forecastrss?w=2502265" );
      InputStream is = oracle.openStream();
      org.w3c.dom.Document doc = null;
      DocumentBuilderFactory domFactory;
      DocumentBuilder builder;
      try {
         domFactory = DocumentBuilderFactory.newInstance();
         domFactory.setNamespaceAware(true);
         builder = domFactory.newDocumentBuilder();
         doc = builder.parse(is);
      } catch (Exception ex) {
         System.err.println("unable to load XML: " + ex);
      }
      XPathFactory factory = XPathFactory.newInstance();
      XPath xpath = factory.newXPath();
      XPathExpression expr = xpath.compile( "//*:*/@*" );
      Object result = expr.evaluate( doc, XPathConstants.NODESET );
      NodeList nl = (NodeList) result;
      for(int j=0 ; j < nl.getLength() ; j++){
         names.add( nl.item(j).getNodeName());
         Node node = nl.item(j);
         String path = "." + node.getNodeName() + " = " + node.getNodeValue();
         node = ((Attr)node).getOwnerElement();
         while( node  != null) {
            path = node.getNodeName() + '/' + path;
            node = node.getParentNode();
         }
         System.out.println( path );
      }
   }
}
Jens Erat
  • 37,523
  • 16
  • 80
  • 96
Aubin
  • 14,617
  • 9
  • 61
  • 84
  • oh, sorry, i already made it like that but the j<2 was a testing thing, i edited the code in my question. – Muhammed Refaat May 19 '13 at 12:02
  • The right XPath expression is //@*, note the cast to Attr and the use of getOwnerElement() in place of getParent() – Aubin May 19 '13 at 12:14
  • The XPath expression was fine but for namespaces (`xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"`), either he would have to use `//*:*/@*` which queries _all_ namespaces or deal with them another way. – Jens Erat May 19 '13 at 12:16
  • well, thx, I got the paths, but not in the proper format, as when i try to query it a got a lot of exceptions, i just wanna paths to use again, the produced paths like (#document/rss/channel/item/yweather:forecast/.code) can't be used. – Muhammed Refaat May 19 '13 at 12:42
  • You missed a `/` between nodes and attributes, I added it. But in the end both queries were equal, and your's was probably the more elegant one. I just wanted to point out the namespace problem. – Jens Erat May 19 '13 at 16:08