3

Dipping my toe in a little Java at the minute and have a question about XPath.

I have a large Xml and I want to use XPath to be able to grab a specific node and then fire further XPath calls against this small chunk of Xml.

Here s rough outline of my Xml:

<Page>
  <ComponentPresentations>
    <ComponentPresentation>
      <Component>
        <Title>
      <ComponentTemplate> 
    <ComponentPresentation>
      <Component>
        <Title>
      <ComponentTemplate> 

My first XPath selects the <Component> node based upon the value of a <ComponenTemplate> Id value:

String componentExpFormat = "/Page/ComponentPresentations/ComponentPresentation/ComponentTemplate/Id[text()='%1$s']/ancestor::ComponentPresentation";
String componentExp = String.format(componentExpFormat, template);
XPathExpression expComponent = xPath.compile(componentExp);
Node componentXml = (Node) expComponent.evaluate(xmldoc, XPathConstants.NODE);

This gives me the <Component> I want but I can;t seem to be able to then XPath against the Node:

String componentExpTitle = "/Component/Fields/item/value/Field/Name[text()='title']/parent::node()/Values/string";                                  
XPathExpression expTitle = xPath.compile(componentExpTitle);
String eventName = expTitle.evaluate(componentXml, XPathConstants.STRING).toString();

Without this I'll have to include the full XPath each time:

/Page/ComponentPresentations/ComponentPresentation/ComponentTemplate/Id[text()='%1$s']/ancestor::ComponentPresentation/Component/Fields/item/value/Field/Name[text()='title']/parent::node()/Values/string

Is that the only way?

Cheers

1
  • Your componentExpTitle is an absolute path, remove the leading slash and try it. Commented May 13, 2013 at 16:42

1 Answer 1

3

An XPath expression with a leading slash

/Component/Fields/item

is absolute, and when you evaluate it with a particular context node it will start looking from the root of the document that the context node belongs to. If you remove the leading slash

Component/Fields/item

it will look for Component children of the context node.

As an aside, you can simplify those XPaths quite a bit, you don't need all the up and down the tree stuff with ancestor::, and you also don't need to use text():

componentExpFormat = "/Page/ComponentPresentations/ComponentPresentation[ComponentTemplate/Id='%1$s']";
componentExpTitle = "Component/Fields/item/value/Field[Name='title']/Values/string";
Sign up to request clarification or add additional context in comments.

1 Comment

Ian, if SO would let me vote more than once I would because you my friend have made the next couple of hours waaaay easier for me - and I've improved my XPath along the way! Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.