Quantcast

Custom Processor with XPath

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Custom Processor with XPath

Castyn
I am attempting to convert a SOAP message from one message format to another, and along the way calculating and aggregating data.  At any rate, I am trying to create a custom processor to do this, within which I will have xpath calls and such.

Currently I am running into an issue trying to convert the message into a org.w3c.dom.Document format for me to use XPath against, and it seems that when I try to

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.w3c.dom.*;

public class HotelProcessor implements Processor {

        public void process(Exchange exchange) throws Exception {
                Document payload = exchange.getIn().getBody(Document.class);

                // XPath stuff to go here

                exchange.getIn().setBody(payload.toString());  // Just temp for testing
        }
}

The payload becomes empty as the next step in the route is a null message.  Any idea what I am doing wrong, or is there a different way I would want to do this all together?  When I use getBody with String.class instead everything works fine, but I can't perform xpath on the payload if I do that.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Custom Processor with XPath

Claus Ibsen-2
Hi

If you use getMandatoryBody then Camel will throw an exception if it
cannot convert to the given type.


On Mon, Nov 21, 2011 at 10:21 PM, Castyn <[hidden email]> wrote:

> I am attempting to convert a SOAP message from one message format to another,
> and along the way calculating and aggregating data.  At any rate, I am
> trying to create a custom processor to do this, within which I will have
> xpath calls and such.
>
> Currently I am running into an issue trying to convert the message into a
> org.w3c.dom.Document format for me to use XPath against, and it seems that
> when I try to
>
> import org.apache.camel.Exchange;
> import org.apache.camel.Processor;
> import org.w3c.dom.*;
>
> public class HotelProcessor implements Processor {
>
>        public void process(Exchange exchange) throws Exception {
>                Document payload = exchange.getIn().getBody(Document.class);
>
>                // XPath stuff to go here
>
>                exchange.getIn().setBody(payload.toString());  // Just temp
> for testing
>        }
> }
>
> The payload becomes empty as the next step in the route is a null message.
> Any idea what I am doing wrong, or is there a different way I would want to
> do this all together?  When I use getBody with String.class instead
> everything works fine, but I can't perform xpath on the payload if I do
> that.
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Custom-Processor-with-XPath-tp5011728p5011728.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



--
Claus Ibsen
-----------------
FuseSource
Email: [hidden email]
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Custom Processor with XPath

Castyn
Good to know.  I have the body properly converting to a Document now.

I suppose this may end up more of an XPath question, so I apologize in advance but I have looked everywhere for some complicated examples and haven't had much luck.

Let's say this is the document that is coming into my custom processor and being converted to a Document:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <soap:Body>
                <ns2:hotelContentResponse xmlns="http://atp.abv.com/schema/common/ATPCommonServiceTypes/v1" 
                                                                  xmlns:ns2="http://atp.abc.com/schema/hotel/hcm/content/serviceDataTypes/v1" 
                                                                  xmlns:ns3="http://atp.abc.com/schema/hotel/hcm/content/dataTypes/v1" 
                                                                  xmlns:ns4="http://atp.abc.com/schema/common/content/serviceDataTypes/v1">
                        <header>
                                <language isoCountryCode="US" isoLanguageCode="en" /> 
                                <headerVersion build="" major="1" minor="0" /> 
                                <transactionStatus overallStatusArea="HOTELCONTENT" overallStatusCode="0000" overallStatusDescription="OK" transactionSuccessful="true" /> 
                                <serviceTransactionDuration endTime="2011-11-21T11:21:46.906-05:00" startTime="2011-11-21T11:21:46.390-05:00" /> 
                        </header>
                        <ns2:hotelContent>
                                <ns4:contentList attributeNumber="718" name="Airport Details">
                                        <ns4:compound attributeId="1390159538" attributeNumber="718" name="Airport Details" valueChangeDate="2009-07-01T04:00:00.000">
                                                <ns4:textLine attributeId="1390159539" attributeNumber="719" name="Airport Code" valueChangeDate="2009-07-01T04:00:00.000">
                                                        <ns4:text>ATL</ns4:text> 
                                                </ns4:textLine>
                                        </ns4:compound>
                                        <ns4:compound attributeId="1390159538" attributeNumber="718" name="Airport Details" valueChangeDate="2009-07-01T04:00:00.000">
                                                <ns4:textLine attributeId="462364234" attributeNumber="719" name="Airport Code" valueChangeDate="2009-07-01T04:00:00.000">
                                                        <ns4:text>NYC</ns4:text> 
                                                </ns4:textLine>
                                        </ns4:compound>
                                </ns4:contentList>
                        </ns2:hotelContent>
                </ns2:hotelContentResponse>
        </soap:Body>
</soap:Envelope>

I am trying to get a Node List of the airport codes (in this doc ATL and NYC).  What I have been trying is

XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("//textLine[attributeNumber='719']");
               
NodeList nodes = (NodeList)expr.evaluate(payload, XPathConstants.NODESET);
           
for (int i = 0; i < nodes.getLength(); i++) {
   // Do Stuff
}

I am not sure if the document needs to have other information attached to it such as XML version for xpath to treat it properly or if it is something else, but I haven't been able to get any nodes returned at all on the document, even when trying expressions as simple as "//hotelContent" and such.  Is there something I am missing?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Custom Processor with XPath

Claus Ibsen-2
XPath can be painful to get working. Usually when nothing comes out,
then its a namespace issue.
XPath must have namespaces defined if your XML have namspaces, which
you do not have.



On Tue, Nov 22, 2011 at 5:02 PM, Castyn <[hidden email]> wrote:

> Good to know.  I have the body properly converting to a Document now.
>
> I suppose this may end up more of an XPath question, so I apologize in
> advance but I have looked everywhere for some complicated examples and
> haven't had much luck.
>
> Let's say this is the document that is coming into my custom processor and
> being converted to a Document:
>
> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
>        <soap:Body>
>                <ns2:hotelContentResponse
> xmlns="http://atp.abv.com/schema/common/ATPCommonServiceTypes/v1"
>
> xmlns:ns2="http://atp.abc.com/schema/hotel/hcm/content/serviceDataTypes/v1"
>
> xmlns:ns3="http://atp.abc.com/schema/hotel/hcm/content/dataTypes/v1"
>
> xmlns:ns4="http://atp.abc.com/schema/common/content/serviceDataTypes/v1">
>                        <header>
>                                <language isoCountryCode="US" isoLanguageCode="en" />
>                                <headerVersion build="" major="1" minor="0" />
>                                <transactionStatus overallStatusArea="HOTELCONTENT"
> overallStatusCode="0000" overallStatusDescription="OK"
> transactionSuccessful="true" />
>                                <serviceTransactionDuration endTime="2011-11-21T11:21:46.906-05:00"
> startTime="2011-11-21T11:21:46.390-05:00" />
>                        </header>
>                        <ns2:hotelContent>
>                                <ns4:contentList attributeNumber="718" name="Airport Details">
>                                        <ns4:compound attributeId="1390159538" attributeNumber="718"
> name="Airport Details" valueChangeDate="2009-07-01T04:00:00.000">
>                                                <ns4:textLine attributeId="1390159539" attributeNumber="719"
> name="Airport Code" valueChangeDate="2009-07-01T04:00:00.000">
>                                                        <ns4:text>ATL</ns4:text>
>                                                </ns4:textLine>
>                                        </ns4:compound>
>                                        <ns4:compound attributeId="1390159538" attributeNumber="718"
> name="Airport Details" valueChangeDate="2009-07-01T04:00:00.000">
>                                                <ns4:textLine attributeId="462364234" attributeNumber="719"
> name="Airport Code" valueChangeDate="2009-07-01T04:00:00.000">
>                                                        <ns4:text>NYC</ns4:text>
>                                                </ns4:textLine>
>                                        </ns4:compound>
>                                </ns4:contentList>
>                        </ns2:hotelContent>
>                </ns2:hotelContentResponse>
>        </soap:Body>
> </soap:Envelope>
>
> I am trying to get a Node List of the airport codes (in this doc ATL and
> NYC).  What I have been trying is
>
> XPath xpath = XPathFactory.newInstance().newXPath();
> XPathExpression expr = xpath.compile("//textLine[attributeNumber='719']");
>
> NodeList nodes = (NodeList)expr.evaluate(payload, XPathConstants.NODESET);
>
> for (int i = 0; i < nodes.getLength(); i++) {
>   // Do Stuff
> }
>
> I am not sure if the document needs to have other information attached to it
> such as XML version for xpath to treat it properly or if it is something
> else, but I haven't been able to get any nodes returned at all on the
> document, even when trying expressions as simple as "//hotelContent" and
> such.  Is there something I am missing?
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Custom-Processor-with-XPath-tp5011728p5013963.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>



--
Claus Ibsen
-----------------
FuseSource
Email: [hidden email]
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Custom Processor with XPath

Castyn
I changed my code to use the NamespaceContext, unfortunately I am still not getting any matches (tried some simpler strings to test as well).  Also, it seems that adding this bit of code really slowed down the processor, though it may just be how many times I have deployed / undeployed the bundle and run it on my local machine.  Any ideas why this would not work?  I am beginning to wonder if writing a custom processor and using xpath is the right way to go, maybe I should be taking the message and just trying to marshal them into the stubs provided with the web service wsdl that the message comes from.  At any rate, here is the processor code thus far.

public void process(Exchange exchange) throws Exception {
        Document payload = exchange.getIn().getMandatoryBody(Document.class);
       
        NamespaceContext ctx = new NamespaceContext() {
            public String getNamespaceURI(String prefix) {
                String uri;
               
                if (prefix.equals("soap"))
                    uri = "http://schemas.xmlsoap.org/soap/envelope/";
                else if (prefix.equals("ns1"))
                    uri = "http://atp.abc.com/schema/common/ATPCommonServiceTypes/v1";
                else if (prefix.equals("ns2"))
                    uri = "http://atp.abc.com/schema/hotel/hcm/content/serviceDataTypes/v1";
                else if (prefix.equals("ns3"))
                    uri = "http://atp.abc.com/schema/hotel/hcm/content/dataTypes/v1";
                else if (prefix.equals("ns4"))
                    uri = "http://atp.abc.com/schema/common/content/serviceDataTypes/v1";
                else
                    uri = null;
                return uri;
            }

          public String getPrefix(String namespaceURI) {return null;}
          public Iterator getPrefixes(String namespaceURI) {return null;}
        };
       
                XPath xpath = XPathFactory.newInstance().newXPath();
                xpath.setNamespaceContext(ctx);
            XPathExpression expr = xpath.compile("//ns4:textLine[attributeNumber='719']");
               
            NodeList nodes = (NodeList)expr.evaluate(payload, XPathConstants.NODESET);
            System.out.println("Node List length = " + nodes.getLength());
           
            for (int i = 0; i < nodes.getLength(); i++) {
            System.out.println(nodes.item(i).getNodeName() + " - " + nodes.item(i).getNodeValue());
            }
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Custom Processor with XPath

Castyn
Figured it out.  I had forgotten the @ sign in the xpath string.
Loading...