Skip to content

Instantly share code, notes, and snippets.

@ledoyen
Created November 17, 2014 14:26
Show Gist options
  • Save ledoyen/0d04230413202ff14a5c to your computer and use it in GitHub Desktop.
Save ledoyen/0d04230413202ff14a5c to your computer and use it in GitHub Desktop.
JDOM2 XPath on CDATA section

Using

  <dependency>
    <groupId>org.jdom</groupId>
    <artifactId>jdom</artifactId>
    <version>2.0.2</version>
  </dependency>
  <dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.1.6</version>
  </dependency>

To use XPath syntax on an XML document wrapped into the CDATA section of another XML document, simply add the following function to the Jaxen context :

import org.jaxen.XPathFunctionContext;

((XPathFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "toXml", new ToXmlFunction());
public class ToXmlFunction implements Function {
	@SuppressWarnings("rawtypes")
	public Object call(Context context, List args) throws FunctionCallException {
		if(args.size() == 1) {
			Object arg = args.get(0);
			if(List.class.isAssignableFrom(arg.getClass()) && ((List)arg).size() == 1) {
				arg = ((List)arg).get(0);
			}
			if(arg instanceof Element) {
				arg = ((Element) arg).getText();
			}
			if(arg instanceof String) {
				try {
					Document doc = toDoc(arg);
					Element dummyRoot = new Element("dummyRoot");
					Element realRoot = doc.getRootElement();
					doc.setRootElement(dummyRoot);
					
					dummyRoot.addContent(realRoot);
					return dummyRoot;
				} catch (JDOMException e) {
					throw new FunctionCallException("toXml() cannot parse XML document.", e);
				} catch (IOException e) {
					throw new FunctionCallException("toXml() cannot parse XML document.", e);
				} catch (JAXBException e) {
					throw new FunctionCallException("toXml() cannot parse XML document.", e);
				}
			} else {
				throw new FunctionCallException("toXml() do not handle [" + arg.getClass() + "]");
			}
		} else {
			throw new FunctionCallException("toXml() requires one argument.");
		}
	}
}

Now using to newly created function you can query the content of a CDATA as long as it is valid XML :

<someroot>
  <node1>
    <![CDATA[
    <subroot>
      <subleaf>Hello world !</subleaf>
    </subroot>
    ]]>
  </node1>
</someroot>
XPathExpression<Object> xpath = XPathFactory.instance().compile("toXml(//node1)/subroot/subleaf/text()");
Object evaluatedValue = xpath.evaluateFirst(document); // String "Hello world !"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment