0

Standard XPath processing in java with javax.xml.xpath works like this:

  1. I provide name for xml to process
  2. I provide xpath expression as a string.
  3. I gain answer stored as a list of nodes, or eventually as a single value depending on what type of output I select.

I need to write a couple of tests in java which basically should work like this: I provide xpath expression as a string and it checks if xpath output of this expression equals to some specified output(also provided as string). So I dont need traversing through node tree and stuff, I just need to gain xpath processor output as a string. Is there any way to do this?

mmmmmm
  • 32,227
  • 27
  • 88
  • 117
archev
  • 21
  • 2
  • 7

2 Answers2

0

XPath.evaluate(expression, inputSource) seems to do what you want.

Edit: Here's some sample code:

String xml = "<foo><bar>text</bar></foo>";
Reader reader = new StringReader(xml);
InputSource inputSource = new InputSource(reader);
XPath xpath = XPathFactory.newInstance().newXPath();
System.out.println(xpath.evaluate("/foo/bar", inputSource));

Edit: this question indicates that there is no java api that can be instantly used to meet your goals. If you're testing XML, then you might want to have a look at XmlUnit

Community
  • 1
  • 1
Buhb
  • 7,088
  • 3
  • 24
  • 38
  • thanks, but this produces somehow "raw" output, for example for "/foo/bar", output is "text" whereas shouldn't it be "text" ? I need full output with tags and stuff – archev Aug 24 '12 at 13:33
0

If you use

xPathExpression.evaluate(document);

where document is your DOM document, then it will return a string representation of the first node it matches. That's probably fine for the use case where you believe that your XPath is selecting a single text node. If that's not the case, you could write some toString() method for NodeList that is returned from:

xPathExpression.evaluate(document, XPathConstants.NODESET);

EDIT 1: Here's a SO article on converting a NodeList to an XML document and printing it.

EDIT 2: If you have XPath expressions that use count or logical operators that return single values, then you could catch the exception thrown and take the appropriate action:

try {
    NodeList nodeList = (NodeList) xPathExpression.evaluate(document, XPathConstants.NODESET);
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node node = nodeList.item(i);
        System.out.println(node.getNodeName());
    }
} catch (XPathExpressionException e) {
    String result = xPathExpression.evaluate(document);
    System.out.println(result);
}
Community
  • 1
  • 1
davidfmatheson
  • 3,539
  • 19
  • 27
  • yeah but sometimes Xpath output is not neccesary a node or node list, it can be also a boolean or integer value, I need a flexible way of gaining output no matter what kind of xpath expression it hadles. – archev Aug 24 '12 at 13:29
  • If you ask if for a `NODESET` it will give you one, even if it's a list of one node with a boolean value or integer value. – davidfmatheson Aug 24 '12 at 13:44
  • Nope, when I do this "XPathException: Can not convert #NUMBER to a NodeList!" occurs – archev Aug 27 '12 at 13:42
  • Post your XPath in your question. This usually happens when you're using something like `count(/foo/bar)`. – davidfmatheson Aug 27 '12 at 13:51
  • when I don't pass any additional argument to evaluate() it returns string containing only first node that matches given expression(no all, which is bad). If I instead pass XPathConstants.NODESET to evaluate(), it works fine if query asks for list of texts, but for count(...) or logical queries it throws exception I posted above. I want code that do not depend of which of NODESET, NUMBER, or BOOLEAN I pass to evaluate() – archev Aug 27 '12 at 14:29
  • XPath in any language will throw that exception if you're purposefully selecting a value instead of a set of nodes. Either you pass in a flag to your method saying "This xPath is special" and take the appropriate action, or just try selecting a `NODESET` and catch the exception. See the edit above. – davidfmatheson Aug 27 '12 at 15:00