You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Castyn <er...@gmail.com> on 2011/11/21 22:21:49 UTC

Custom Processor with XPath

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.

Re: Custom Processor with XPath

Posted by Castyn <er...@gmail.com>.
Figured it out.  I had forgotten the @ sign in the xpath string.

--
View this message in context: http://camel.465427.n5.nabble.com/Custom-Processor-with-XPath-tp5011728p5014998.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Custom Processor with XPath

Posted by Castyn <er...@gmail.com>.
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()); 
	    }		


--
View this message in context: http://camel.465427.n5.nabble.com/Custom-Processor-with-XPath-tp5011728p5014112.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Re: Custom Processor with XPath

Posted by Claus Ibsen <cl...@gmail.com>.
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 <er...@gmail.com> 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: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/

Re: Custom Processor with XPath

Posted by Castyn <er...@gmail.com>.
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.

Re: Custom Processor with XPath

Posted by Claus Ibsen <cl...@gmail.com>.
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 <er...@gmail.com> 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: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/