0

I have XML similar in structure to the below example stored in a Camel header as a String:

<list>
   <library>
      <name>xxx</name>
      <address>
         <line1>aaa</line1>
         <line2>bbb</line2>
         <line3>ccc</line3>
      </address>
   </library>
   <book>
      <author>
         <name>John</name>
         <number>4324234</number>
      </author>
      <title>New Book</title>
      <isbn>dsdaassda</isbn>
   </book>
   <book>...</book>
   <book>...</book>
</list>

I would like to extract the library element into another Camel header

   <library>
      <name>xxx</name>
      <address>
         <line1>aaa</line1>
         <line2>bbb</line2>
         <line3>ccc</line3>
      </address>
   </library>

How can I achieve this using Camel Java DSL?

(My main source of confusion is applying the XPath to an exchange header item rather than the body)

2
  • Do you need the xpath expression ? Commented Mar 20, 2018 at 10:17
  • Can normal java code be used here instead of using Camel Java DSL? Commented Mar 20, 2018 at 10:51

4 Answers 4

3

This should work:

.xpath("[your XPath expression]", "[the name of the header to select from]")

Your use case could be done like this

from("direct:input")
    .setHeader("newHeader").xpath("[your XPath]", "[xmlHeader]")
    .to("...");

You can find this also in the Camel docs, Section Using XPath on Headers.

And it is for example used in this Camel unit test, in the route at the bottom of the file.

Sign up to request clarification or add additional context in comments.

10 Comments

Did you check if this works. Second argument to xpath is not a string, May be it was in older versions. Current version takes a second argument of type Class<?>
Those doc's are old. Check out the latest version and try
Works like a charm. At least for a when condition in a content based router.
I added an example how to extract the XPath result into a new header.
which version of apache-camel are you using?
|
0

Try this.

@Override
public void configure() throws Exception {
    XPathExpression xPathExpression = new XPathExpression();
    xPathExpression.setHeaderName("completexml"); //assuming the header name of the xml as completexml
    xPathExpression.setExpression("/list/library");

    from("direct:abc")
         .setHeader("OriginalBody", simple("${body}")) //get original body
         .split(xPathExpression) //split according to xPathExpression
         .setHeader("library", simple("${body}")) //set new header with only library element
         .setBody(simple("${header.OriginalBody}")) //set the original body back
         //.log("${header.completexml}")
         //.log("${header.library}")
         //.log("${body}")
        ;
}

As per the answer here, we could give a second argument to xpath which is of type String. But With the latest version, I don't see any such method in xpath which takes a second argument as String. May be it is removed in newer versions.

What I am doing is storing the original body in a header(since after split, original body is replaced by the result of split), then replacing it.

Comments

0

Here's a working example of JUnit test:

@Override
protected RouteBuilder createRouteBuilder() {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            from("direct:start")
                    .routeId("xpathTest")
            .log(LoggingLevel.INFO, "XML input : \n${body}")
            .setHeader("XNODE").xpath("/list/library", NodeList.class)
            .setBody().xpath("/list/library", NodeList.class)
            .to("log:end?level=INFO&showAll=true&multiline=true");
        }
    };
}

Оutput log:

2018-03-22 00:50:00,141 [main           ] INFO  end                            - Exchange[
, Id: ID-BlackMirror-10897-1521668997689-0-2
, ExchangePattern: InOnly
, Properties: {CamelCreatedTimestamp=Thu Mar 22 00:49:59 MSK 2018, CamelMessageHistory=[DefaultMessageHistory[routeId=xpathTest, node=log1], DefaultMessageHistory[routeId=xpathTest, node=setHeader1], DefaultMessageHistory[routeId=xpathTest, node=setBody1], DefaultMessageHistory[routeId=xpathTest, node=to1]], CamelToEndpoint=log://end?level=INFO&multiline=true&showAll=true}
, Headers: {breadcrumbId=ID-BlackMirror-10897-1521668997689-0-1, XNODE=org.apache.xml.dtm.ref.DTMNodeList@5acf93bb}
, BodyType: org.apache.xml.dtm.ref.DTMNodeList
, Body: <library>       <name>xxx</name>       <address>          <line1>aaa</line1>          <line2>bbb</line2>          <line3>ccc</line3>       </address>    </library>
, Out: null: 

So for the header you need an expression:

.setHeader("XNODE").xpath("/list/library", NodeList.class)

and for the body:

.setBody().xpath("/list/library", NodeList.class)

Comments

0

You can do it:

.setHeader("yourHeaderName", xpath("//*[local-name()='library']").stringResult())

So you will have the library structure for work

Comments

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.