How to pass variable parameter into XPath expression?

I want to pass a parameter into an XPath expression.

(//a/b/c[x=?],myParamForXAttribute)

Can I do this with XPath 1.0 ? (I tried string-join but it is not there in XPath 1.0)

Then how can I do this ?

My XML looks like

<a>
 <b>
  <c>
   <x>val1</x>
   <y>abc</y>
  </c>
  <c>
   <x>val2</x>
   <y>abcd</y>
  </c>
</b>
</a>

I want to get <y> element value where x element value is val1

I tried //a/b/c[x='val1']/y but it did not work.


Solution 1:

Given that you're using the Axiom XPath library, which in turn uses Jaxen, you'll need to follow the following three steps to do this in a thoroughly robust manner:

  • Create a SimpleVariableContext, and call context.setVariableValue("val", "value1") to assign a value to that variable.
  • On your BaseXPath object, call .setVariableContext() to pass in the context you assigned.
  • Inside your expression, use /a/b/c[x=$val]/y to refer to that value.

Consider the following:

package com.example;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.common.AxiomText;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.axiom.om.xpath.DocumentNavigator;
import org.jaxen.*;

import javax.xml.stream.XMLStreamException;

public class Main {

    public static void main(String[] args) throws XMLStreamException, JaxenException {
        String xmlPayload="<parent><a><b><c><x>val1</x><y>abc</y></c>" +
                                        "<c><x>val2</x><y>abcd</y></c>" +
                          "</b></a></parent>";
        OMElement xmlOMOBject = AXIOMUtil.stringToOM(xmlPayload);

        SimpleVariableContext svc = new SimpleVariableContext();
        svc.setVariableValue("val", "val2");

        String xpartString = "//c[x=$val]/y/text()";
        BaseXPath contextpath = new BaseXPath(xpartString, new DocumentNavigator());
        contextpath.setVariableContext(svc);
        AxiomText selectedNode = (AxiomText) contextpath.selectSingleNode(xmlOMOBject);
        System.out.println(selectedNode.getText());
    }
}

...which emits as output:

abcd

Solution 2:

It depends on the language in which you're using XPath.

In XSLT:

 "//a/b/c[x=$myParamForXAttribute]"

Note that, unlike the approach above, the three below are open to XPath injection attacks and should never be used with uncontrolled or untrusted inputs; to avoid this, use a mechanism provided by your language or library to pass in variables out-of-band. [Credit: Charles Duffy]

In C#:

String.Format("//a/b/c[x={0}]", myParamForXAttribute);

In Java:

String.format("//a/b/c[x=%s]", myParamForXAttribute);

In Python:

 "//a/b/c[x={}]".format(myParamForXAttribute)