You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Greg Barker <fl...@fletchowns.net> on 2013/05/23 23:02:08 UTC

Specifying order of XML elements at runtime?

Hello -

I'm using the Apache CXF WebClient for a project, and the REST API I am
interacting with has a requirement that XML elements are sent in a specific
order, and "correct" order can change depending on certain settings that
are not known at compile time.

I've found that the XmlType.propOrder annotation allows me to specify the
order in which I want the XML elements to appear at compile time. This
works great. The problem is that I need to be able to change this order at
runtime, and I cannot figure out a way to do that without resorting to
ugly/hacky solutions that modify the annotation at runtime.

Is there an easy way to specify XML element order dynamically at runtime?

Thanks!
Greg

Re: Specifying order of XML elements at runtime?

Posted by Greg Barker <fl...@fletchowns.net>.
Daniel - thank you for your suggestion, I'll explore that option as well.


On Wed, May 29, 2013 at 1:12 PM, Daniel Kulp <dk...@apache.org> wrote:

>
> On May 23, 2013, at 5:02 PM, Greg Barker <fl...@fletchowns.net> wrote:
>
> > Hello -
> >
> > I'm using the Apache CXF WebClient for a project, and the REST API I am
> > interacting with has a requirement that XML elements are sent in a
> specific
> > order, and "correct" order can change depending on certain settings that
> > are not known at compile time.
> >
> > I've found that the XmlType.propOrder annotation allows me to specify the
> > order in which I want the XML elements to appear at compile time. This
> > works great. The problem is that I need to be able to change this order
> at
> > runtime, and I cannot figure out a way to do that without resorting to
> > ugly/hacky solutions that modify the annotation at runtime.
> >
> > Is there an easy way to specify XML element order dynamically at runtime?
>
> There really isn't an "easy" way to do this.  You can look at:
>
> https://community.jboss.org/wiki/JAXBIntroductions
>
> where they use some hooks into the JAXB RI's runtime to provide a listener
> that would "mimic" some of the annotations.  You may be able to use some of
> their code to write a listener to mimic the XmlType.propOrder stuff.    Not
> sure.   Never really tried.
>
>
>
> --
> Daniel Kulp
> dkulp@apache.org - http://dankulp.com/blog
> Talend Community Coder - http://coders.talend.com
>
>

Re: Specifying order of XML elements at runtime?

Posted by Daniel Kulp <dk...@apache.org>.
On May 23, 2013, at 5:02 PM, Greg Barker <fl...@fletchowns.net> wrote:

> Hello -
> 
> I'm using the Apache CXF WebClient for a project, and the REST API I am
> interacting with has a requirement that XML elements are sent in a specific
> order, and "correct" order can change depending on certain settings that
> are not known at compile time.
> 
> I've found that the XmlType.propOrder annotation allows me to specify the
> order in which I want the XML elements to appear at compile time. This
> works great. The problem is that I need to be able to change this order at
> runtime, and I cannot figure out a way to do that without resorting to
> ugly/hacky solutions that modify the annotation at runtime.
> 
> Is there an easy way to specify XML element order dynamically at runtime?

There really isn't an "easy" way to do this.  You can look at:

https://community.jboss.org/wiki/JAXBIntroductions

where they use some hooks into the JAXB RI's runtime to provide a listener that would "mimic" some of the annotations.  You may be able to use some of their code to write a listener to mimic the XmlType.propOrder stuff.    Not sure.   Never really tried.



-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com


RE: Specifying order of XML elements at runtime?

Posted by Andrei Shakirin <as...@talend.com>.
Hi Greg,

>Of course as soon as I send the email it hits me - the order in which the interceptors are added is probably significant. Added the LoggingOutInterceptor AFTER my XSLTOutInterceptor and now the logging >messages reflect my XSLT.

Yep, the order of interceptors is exactly the point.

> Again many thanks for all your help (and Sergey). Where do I send the beers? :)

Nice that you got it working!

Regards,
Andrei.

From: Greg Barker [mailto:fletch@fletchowns.net] 
Sent: Mittwoch, 5. Juni 2013 20:53
To: Andrei Shakirin
Cc: users@cxf.apache.org
Subject: Re: Specifying order of XML elements at runtime?

Of course as soon as I send the email it hits me - the order in which the interceptors are added is probably significant. Added the LoggingOutInterceptor AFTER my XSLTOutInterceptor and now the logging messages reflect my XSLT.

On Wed, Jun 5, 2013 at 11:45 AM, Greg Barker <fl...@fletchowns.net> wrote:
Thanks a ton Andrei. Added Saxon-HE to my pom and set that TransformerFactory property per your suggestion, and it appears to work great. I thought it wasn't working at first when looking at the LoggingOutInterceptor output, but after examining the payload server side the effect of my XSLT is apparent. Out of curiosity, is that expected? I also noticed the LoggingOutInterceptor output did not reflect when I crossed the 4096 byte threshold and the WebClient went into chunked transfer encoding.
Again many thanks for all your help (and Sergey). Where do I send the beers? :)

Greg

On Tue, Jun 4, 2013 at 1:48 AM, Andrei Shakirin <as...@talend.com> wrote:
Hi Greg,

>It seems to work ok using this XSLT testing utility but it doesn't seem to do anything at all in CXF using:
>XSLTOutInterceptor outInterceptor = new XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null, "test.xsl");
>config.getOutInterceptors().add(outInterceptor);
By default CXF XSLT feature uses Xalan TransformerFactory from JDK, which supports only XSLT 1.0.
You have two ways:
a) Rewrite your transformation using XSLT 1.0 (as a sample please look in http://svn.apache.org/repos/asf/cxf/trunk/systests/uncategorized/src/test/java/org/apache/cxf/systest/transform/feature/TransformFeatureTest.java  and http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/test/java/org/apache/cxf/feature/transform/XSLTInterceptorsTest.java )

b) Use other XSLT engine supporting XSLT 2.0 (for example SAXON http://saxon.sourceforge.net/)
I have never tested it, but TransformerFactory.newInstance() should obtain SAXON factory, if you specify following java option:
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl") and have SAXON jars on your classpath;

Regards,
Andrei.

From: Greg Barker [mailto:fletch@fletchowns.net]
Sent: Montag, 3. Juni 2013 20:27
To: Andrei Shakirin
Cc: users@cxf.apache.org
Subject: Re: Specifying order of XML elements at runtime?

How does the transformation feature work if there are more than 1 of the element being transformed?

For example:
<Container xmlns="http://something">
    <Parent>
        <Child1>P1C1</Child1>
        <Child2>P1C2</Child2>
        <Child3>P1C3</Child3>
    </Parent>
    <Parent>
        <Child1>P2C1</Child1>
        <Child2>P2C3</Child2>
    </Parent>
</Container>

After using the following:
TransformOutInterceptor transformOutInterceptor = new TransformOutInterceptor();
transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child1", ""));
transformOutInterceptor.setOutAppendElements(Collections.singletonMap("{http://something}Child3", "{http://something}Child1=P1C1"));
Here's the XML I end up with:
<Container xmlns="http://something">
    <Parent>
        <Child2>P1C2</Child2>
        <Child1>P1C1</Child1>
        <Child3>P1C3</Child3>
    </Parent>
    <Parent>
        <Child2>P2C3</Child2>
    </Parent>
</Container>
So it looks like the setOutTransformElements got applied to both Parent elements, but the setOutAppendElements only got applied to the first. Is there a way to apply the setOutAppendElements to both Parent elements, each having a different transformed value? (i also though Child1 would end up after Child3, not before it)

I couldn't figure out a way to do that so I started going the XSLT route. Here's what I ended up with:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="2.0"  xpath-default-namespace="http://something">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="Parent">
    <xsl:copy>
      <xsl:apply-templates select="Child3"/>
      <xsl:apply-templates select="Child2"/>
      <xsl:apply-templates select="Child1"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
It seems to work ok using this XSLT testing utility but it doesn't seem to do anything at all in CXF using:
XSLTOutInterceptor outInterceptor = new XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null, "test.xsl");
config.getOutInterceptors().add(outInterceptor);

Is there something unsupported in that xslt that I'm trying to use?
Many thanks for taking the time to help me with this, I really appreciate it.
Greg


On Fri, May 31, 2013 at 5:52 AM, Andrei Shakirin <as...@talend.com> wrote:
Hi Greg,

>Thank you for your input Andrei. I had been relying on LoggingOutInterceptor messages to see what the XML looked like so I thought maybe it was not accurate so I changed it to post the XML to a localhost >endpoint and rely on server side logging to see what the XML payload looked like. It confirmed the behavior I was seeing before.
>Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am seeing much different behavior now - it matches how you describe it should be working. So I guess it was a bug that was fixed at some >point.
Obviously yes.

>If I have to specify the element values when I call setInAppendElements, I guess I'll have to be manipulating the TransformOutInterceptor a lot more frequently than I had anticipated. Do I also need to handle >escaping of XML entity characters?
I do not think that you should escape characters, XMLStreamWriter.writeCharacters() should do it per spec: "However the writeCharacters method is required to escape & , < and > For attribute values the writeAttribute method will escape the above characters plus " to ensure that all character content and attribute values are well formed".

Regards,
Andrei.

From: Greg Barker [mailto:fletch@fletchowns.net]
Sent: Freitag, 31. Mai 2013 04:56
To: Andrei Shakirin
Cc: users@cxf.apache.org
Subject: Re: Specifying order of XML elements at runtime?

Thank you for your input Andrei. I had been relying on LoggingOutInterceptor messages to see what the XML looked like so I thought maybe it was not accurate so I changed it to post the XML to a localhost endpoint and rely on server side logging to see what the XML payload looked like. It confirmed the behavior I was seeing before.
Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am seeing much different behavior now - it matches how you describe it should be working. So I guess it was a bug that was fixed at some point.
If I have to specify the element values when I call setInAppendElements, I guess I'll have to be manipulating the TransformOutInterceptor a lot more frequently than I had anticipated. Do I also need to handle escaping of XML entity characters?

On Wed, May 29, 2013 at 7:05 AM, Andrei Shakirin <as...@talend.com> wrote:
Hi Greg,

Sergei is in vacation this week, I will try to answer your question.

transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child1", "")) should remove only Child1 element with all his children.
Not sure why it results removing Parent children, are you sure with that test?

What you basically need to delete and elements and insert it in different order is something like this:

transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child2", ""));
transformOutInterceptor.setInAppendElements(Collections.singletonMap("{http://something}Child1", "{http://something}Child2=Another Value"));

If it not enough you can use XSLT Feature http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to your request/response.

Other alternative is to create own interceptor, put it to POST_PROTOCOL phase and sort elements in message payload as you want.

Regards,
Andrei.

> -----Original Message-----
> From: Greg Barker [mailto:fletch@fletchowns.net]
> Sent: Samstag, 25. Mai 2013 02:09
> To: users@cxf.apache.org
> Subject: Re: Specifying order of XML elements at runtime?
>
> Thanks for the quick reply Sergey!
>
> I'm having a bit a trouble with the suggested solution though, almost
> certainly a pilot error on my part I assume.
>
> XML before:
> <Container xmlns="http://something">
>     <Parent>
>         <Child1>Some Value</Child1>
>         <Child2>Another Value</Child2>
>     </Parent>
> </Container>
>
> So I tried:
> transformOutInterceptor.setOutDropElements(Collections.singletonList("{
> http://something}Child1"));
>
> Which results in:
> <Container xmlns="http://something">
>     <Parent>
>         Some Value
>         <Child2>Another Value</Child2>
>     </Parent>
> </Container>
>
> Got rid of the element...but not the value. So I tried the "deep-drop"
> described on that link:
> transformOutInterceptor.setOutTransformElements(Collections.singletonM
> ap("{
> http://something}Child1", ""));
>
> Which resulted in:
> <Container xmlns="http://something">
>     <Parent/>
> </Container>
>
> What am I screwing up? I basically just want to end up with:
> <Container xmlns="http://something">
>     <Parent>
>         <Child2>Another Value</Child2>
>         <Child1>Some Value</Child1>
>     </Parent>
>           </Container>
>
> Many Thanks!
> Greg
>
>
> On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
> <sb...@gmail.com>wrote:
>
> > Hi
> >
> > On 23/05/13 22:02, Greg Barker wrote:
> >
> >> Hello -
> >>
> >> I'm using the Apache CXF WebClient for a project, and the REST API I
> >> am interacting with has a requirement that XML elements are sent in a
> >> specific order, and "correct" order can change depending on certain
> >> settings that are not known at compile time.
> >>
> >> I've found that the XmlType.propOrder annotation allows me to specify
> >> the order in which I want the XML elements to appear at compile time.
> >> This works great. The problem is that I need to be able to change
> >> this order at runtime, and I cannot figure out a way to do that
> >> without resorting to ugly/hacky solutions that modify the annotation at
> runtime.
> >>
> >> Is there an easy way to specify XML element order dynamically at
> runtime?
> >>
> >>  Try Transformation feature:
> >
> > http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apa
> > che.org/docs/transformationfeature.html>
> >
> > Use outDropElements and outAppendElements properties.
> >
> > Suppose you have the following produced by default:
> > <request>
> >   <a/>
> >   <b/>
> > </request>
> >
> > if needed, you can get <a/> dropped with outDropElements and then
> > added immediately after <b/> with outAppendElements.
> >
> > If that has to be set up dynamically then add the feature or its
> > interceptors from the code, similarly to
> > http://cxf.apache.org/docs/**transformationfeature.html#**
> > TransformationFeature-
> **Configuringthefeaturefromtheco**de<http://cxf.
> > apache.org/docs/transformationfeature.html#TransformationFeature-
> Confi
> > guringthefeaturefromthecode>
> >
> > HTH, Sergey
> >
> >  Thanks!
> >> Greg
> >>
> >>
> >



Re: Specifying order of XML elements at runtime?

Posted by Greg Barker <fl...@fletchowns.net>.
Of course as soon as I send the email it hits me - the order in which the
interceptors are added is probably significant. Added the
LoggingOutInterceptor AFTER my XSLTOutInterceptor and now the logging
messages reflect my XSLT.


On Wed, Jun 5, 2013 at 11:45 AM, Greg Barker <fl...@fletchowns.net> wrote:

> Thanks a ton Andrei. Added Saxon-HE to my pom and set that
> TransformerFactory property per your suggestion, and it appears to work
> great. I thought it wasn't working at first when looking at the
> LoggingOutInterceptor output, but after examining the payload server side
> the effect of my XSLT is apparent. Out of curiosity, is that expected? I
> also noticed the LoggingOutInterceptor output did not reflect when I
> crossed the 4096 byte threshold and the WebClient went into chunked
> transfer encoding.
>
> Again many thanks for all your help (and Sergey). Where do I send the
> beers? :)
>
> Greg
>
>
> On Tue, Jun 4, 2013 at 1:48 AM, Andrei Shakirin <as...@talend.com>wrote:
>
>> Hi Greg,
>>
>> >It seems to work ok using this XSLT testing utility but it doesn't seem
>> to do anything at all in CXF using:
>> >XSLTOutInterceptor outInterceptor = new
>> XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null,
>> "test.xsl");
>> >config.getOutInterceptors().add(outInterceptor);
>>
>> By default CXF XSLT feature uses Xalan TransformerFactory from JDK, which
>> supports only XSLT 1.0.
>> You have two ways:
>> a) Rewrite your transformation using XSLT 1.0 (as a sample please look in
>> http://svn.apache.org/repos/asf/cxf/trunk/systests/uncategorized/src/test/java/org/apache/cxf/systest/transform/feature/TransformFeatureTest.java and
>> http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/test/java/org/apache/cxf/feature/transform/XSLTInterceptorsTest.java)
>>
>> b) Use other XSLT engine supporting XSLT 2.0 (for example SAXON
>> http://saxon.sourceforge.net/)
>> I have never tested it, but TransformerFactory.newInstance() should
>> obtain SAXON factory, if you specify following java option:
>> System.setProperty("javax.xml.transform.TransformerFactory",
>> "net.sf.saxon.TransformerFactoryImpl") and have SAXON jars on your
>> classpath;
>>
>> Regards,
>> Andrei.
>>
>> From: Greg Barker [mailto:fletch@fletchowns.net]
>> Sent: Montag, 3. Juni 2013 20:27
>> To: Andrei Shakirin
>> Cc: users@cxf.apache.org
>> Subject: Re: Specifying order of XML elements at runtime?
>>
>> How does the transformation feature work if there are more than 1 of the
>> element being transformed?
>>
>> For example:
>> <Container xmlns="http://something">
>>     <Parent>
>>         <Child1>P1C1</Child1>
>>         <Child2>P1C2</Child2>
>>         <Child3>P1C3</Child3>
>>     </Parent>
>>     <Parent>
>>         <Child1>P2C1</Child1>
>>         <Child2>P2C3</Child2>
>>     </Parent>
>> </Container>
>>
>> After using the following:
>> TransformOutInterceptor transformOutInterceptor = new
>> TransformOutInterceptor();
>>
>> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
>> http://something}Child1", ""));
>> transformOutInterceptor.setOutAppendElements(Collections.singletonMap("{
>> http://something}Child3", "{http://something}Child1=P1C1"));
>> Here's the XML I end up with:
>> <Container xmlns="http://something">
>>     <Parent>
>>         <Child2>P1C2</Child2>
>>         <Child1>P1C1</Child1>
>>         <Child3>P1C3</Child3>
>>     </Parent>
>>     <Parent>
>>         <Child2>P2C3</Child2>
>>     </Parent>
>> </Container>
>> So it looks like the setOutTransformElements got applied to both Parent
>> elements, but the setOutAppendElements only got applied to the first. Is
>> there a way to apply the setOutAppendElements to both Parent elements, each
>> having a different transformed value? (i also though Child1 would end up
>> after Child3, not before it)
>>
>> I couldn't figure out a way to do that so I started going the XSLT route.
>> Here's what I ended up with:
>> <?xml version="1.0" encoding="UTF-8"?>
>> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>> version="2.0"  xpath-default-namespace="http://something">
>>   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
>>   <xsl:template match="node() | @*">
>>     <xsl:copy>
>>       <xsl:apply-templates select="node() | @*"/>
>>     </xsl:copy>
>>   </xsl:template>
>>   <xsl:template match="Parent">
>>     <xsl:copy>
>>       <xsl:apply-templates select="Child3"/>
>>       <xsl:apply-templates select="Child2"/>
>>       <xsl:apply-templates select="Child1"/>
>>     </xsl:copy>
>>   </xsl:template>
>> </xsl:stylesheet>
>> It seems to work ok using this XSLT testing utility but it doesn't seem
>> to do anything at all in CXF using:
>> XSLTOutInterceptor outInterceptor = new
>> XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null,
>> "test.xsl");
>> config.getOutInterceptors().add(outInterceptor);
>>
>> Is there something unsupported in that xslt that I'm trying to use?
>> Many thanks for taking the time to help me with this, I really appreciate
>> it.
>> Greg
>>
>>
>> On Fri, May 31, 2013 at 5:52 AM, Andrei Shakirin <as...@talend.com>
>> wrote:
>> Hi Greg,
>>
>> >Thank you for your input Andrei. I had been relying on
>> LoggingOutInterceptor messages to see what the XML looked like so I thought
>> maybe it was not accurate so I changed it to post the XML to a localhost
>> >endpoint and rely on server side logging to see what the XML payload
>> looked like. It confirmed the behavior I was seeing before.
>> >Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
>> seeing much different behavior now - it matches how you describe it should
>> be working. So I guess it was a bug that was fixed at some >point.
>> Obviously yes.
>>
>> >If I have to specify the element values when I call setInAppendElements,
>> I guess I'll have to be manipulating the TransformOutInterceptor a lot more
>> frequently than I had anticipated. Do I also need to handle >escaping of
>> XML entity characters?
>> I do not think that you should escape characters,
>> XMLStreamWriter.writeCharacters() should do it per spec: "However the
>> writeCharacters method is required to escape & , < and > For attribute
>> values the writeAttribute method will escape the above characters plus " to
>> ensure that all character content and attribute values are well formed".
>>
>> Regards,
>> Andrei.
>>
>> From: Greg Barker [mailto:fletch@fletchowns.net]
>> Sent: Freitag, 31. Mai 2013 04:56
>> To: Andrei Shakirin
>> Cc: users@cxf.apache.org
>> Subject: Re: Specifying order of XML elements at runtime?
>>
>> Thank you for your input Andrei. I had been relying on
>> LoggingOutInterceptor messages to see what the XML looked like so I thought
>> maybe it was not accurate so I changed it to post the XML to a localhost
>> endpoint and rely on server side logging to see what the XML payload looked
>> like. It confirmed the behavior I was seeing before.
>> Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
>> seeing much different behavior now - it matches how you describe it should
>> be working. So I guess it was a bug that was fixed at some point.
>> If I have to specify the element values when I call setInAppendElements,
>> I guess I'll have to be manipulating the TransformOutInterceptor a lot more
>> frequently than I had anticipated. Do I also need to handle escaping of XML
>> entity characters?
>>
>> On Wed, May 29, 2013 at 7:05 AM, Andrei Shakirin <as...@talend.com>
>> wrote:
>> Hi Greg,
>>
>> Sergei is in vacation this week, I will try to answer your question.
>>
>>
>> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
>> http://something}Child1", "")) should remove only Child1 element with
>> all his children.
>> Not sure why it results removing Parent children, are you sure with that
>> test?
>>
>> What you basically need to delete and elements and insert it in different
>> order is something like this:
>>
>>
>> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
>> http://something}Child2", ""));
>> transformOutInterceptor.setInAppendElements(Collections.singletonMap("{
>> http://something}Child1", "{http://something}Child2=Another Value"));
>>
>> If it not enough you can use XSLT Feature
>> http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to
>> your request/response.
>>
>> Other alternative is to create own interceptor, put it to POST_PROTOCOL
>> phase and sort elements in message payload as you want.
>>
>> Regards,
>> Andrei.
>>
>> > -----Original Message-----
>> > From: Greg Barker [mailto:fletch@fletchowns.net]
>> > Sent: Samstag, 25. Mai 2013 02:09
>> > To: users@cxf.apache.org
>> > Subject: Re: Specifying order of XML elements at runtime?
>> >
>> > Thanks for the quick reply Sergey!
>> >
>> > I'm having a bit a trouble with the suggested solution though, almost
>> > certainly a pilot error on my part I assume.
>> >
>> > XML before:
>> > <Container xmlns="http://something">
>> >     <Parent>
>> >         <Child1>Some Value</Child1>
>> >         <Child2>Another Value</Child2>
>> >     </Parent>
>> > </Container>
>> >
>> > So I tried:
>> > transformOutInterceptor.setOutDropElements(Collections.singletonList("{
>> > http://something}Child1"));
>> >
>> > Which results in:
>> > <Container xmlns="http://something">
>> >     <Parent>
>> >         Some Value
>> >         <Child2>Another Value</Child2>
>> >     </Parent>
>> > </Container>
>> >
>> > Got rid of the element...but not the value. So I tried the "deep-drop"
>> > described on that link:
>> > transformOutInterceptor.setOutTransformElements(Collections.singletonM
>> > ap("{
>> > http://something}Child1", ""));
>> >
>> > Which resulted in:
>> > <Container xmlns="http://something">
>> >     <Parent/>
>> > </Container>
>> >
>> > What am I screwing up? I basically just want to end up with:
>> > <Container xmlns="http://something">
>> >     <Parent>
>> >         <Child2>Another Value</Child2>
>> >         <Child1>Some Value</Child1>
>> >     </Parent>
>> >           </Container>
>> >
>> > Many Thanks!
>> > Greg
>> >
>> >
>> > On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
>> > <sb...@gmail.com>wrote:
>> >
>> > > Hi
>> > >
>> > > On 23/05/13 22:02, Greg Barker wrote:
>> > >
>> > >> Hello -
>> > >>
>> > >> I'm using the Apache CXF WebClient for a project, and the REST API I
>> > >> am interacting with has a requirement that XML elements are sent in a
>> > >> specific order, and "correct" order can change depending on certain
>> > >> settings that are not known at compile time.
>> > >>
>> > >> I've found that the XmlType.propOrder annotation allows me to specify
>> > >> the order in which I want the XML elements to appear at compile time.
>> > >> This works great. The problem is that I need to be able to change
>> > >> this order at runtime, and I cannot figure out a way to do that
>> > >> without resorting to ugly/hacky solutions that modify the annotation
>> at
>> > runtime.
>> > >>
>> > >> Is there an easy way to specify XML element order dynamically at
>> > runtime?
>> > >>
>> > >>  Try Transformation feature:
>> > >
>> > > http://cxf.apache.org/docs/**transformationfeature.html<
>> http://cxf.apa
>> > > che.org/docs/transformationfeature.html>
>> > >
>> > > Use outDropElements and outAppendElements properties.
>> > >
>> > > Suppose you have the following produced by default:
>> > > <request>
>> > >   <a/>
>> > >   <b/>
>> > > </request>
>> > >
>> > > if needed, you can get <a/> dropped with outDropElements and then
>> > > added immediately after <b/> with outAppendElements.
>> > >
>> > > If that has to be set up dynamically then add the feature or its
>> > > interceptors from the code, similarly to
>> > > http://cxf.apache.org/docs/**transformationfeature.html#**
>> > > TransformationFeature-
>> > **Configuringthefeaturefromtheco**de<http://cxf.
>> > > apache.org/docs/transformationfeature.html#TransformationFeature-
>> > Confi
>> > > guringthefeaturefromthecode>
>> > >
>> > > HTH, Sergey
>> > >
>> > >  Thanks!
>> > >> Greg
>> > >>
>> > >>
>> > >
>>
>>
>

Re: Specifying order of XML elements at runtime?

Posted by Greg Barker <fl...@fletchowns.net>.
Thanks a ton Andrei. Added Saxon-HE to my pom and set that
TransformerFactory property per your suggestion, and it appears to work
great. I thought it wasn't working at first when looking at the
LoggingOutInterceptor output, but after examining the payload server side
the effect of my XSLT is apparent. Out of curiosity, is that expected? I
also noticed the LoggingOutInterceptor output did not reflect when I
crossed the 4096 byte threshold and the WebClient went into chunked
transfer encoding.

Again many thanks for all your help (and Sergey). Where do I send the
beers? :)

Greg


On Tue, Jun 4, 2013 at 1:48 AM, Andrei Shakirin <as...@talend.com>wrote:

> Hi Greg,
>
> >It seems to work ok using this XSLT testing utility but it doesn't seem
> to do anything at all in CXF using:
> >XSLTOutInterceptor outInterceptor = new
> XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null,
> "test.xsl");
> >config.getOutInterceptors().add(outInterceptor);
>
> By default CXF XSLT feature uses Xalan TransformerFactory from JDK, which
> supports only XSLT 1.0.
> You have two ways:
> a) Rewrite your transformation using XSLT 1.0 (as a sample please look in
> http://svn.apache.org/repos/asf/cxf/trunk/systests/uncategorized/src/test/java/org/apache/cxf/systest/transform/feature/TransformFeatureTest.java and
> http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/test/java/org/apache/cxf/feature/transform/XSLTInterceptorsTest.java)
>
> b) Use other XSLT engine supporting XSLT 2.0 (for example SAXON
> http://saxon.sourceforge.net/)
> I have never tested it, but TransformerFactory.newInstance() should obtain
> SAXON factory, if you specify following java option:
> System.setProperty("javax.xml.transform.TransformerFactory",
> "net.sf.saxon.TransformerFactoryImpl") and have SAXON jars on your
> classpath;
>
> Regards,
> Andrei.
>
> From: Greg Barker [mailto:fletch@fletchowns.net]
> Sent: Montag, 3. Juni 2013 20:27
> To: Andrei Shakirin
> Cc: users@cxf.apache.org
> Subject: Re: Specifying order of XML elements at runtime?
>
> How does the transformation feature work if there are more than 1 of the
> element being transformed?
>
> For example:
> <Container xmlns="http://something">
>     <Parent>
>         <Child1>P1C1</Child1>
>         <Child2>P1C2</Child2>
>         <Child3>P1C3</Child3>
>     </Parent>
>     <Parent>
>         <Child1>P2C1</Child1>
>         <Child2>P2C3</Child2>
>     </Parent>
> </Container>
>
> After using the following:
> TransformOutInterceptor transformOutInterceptor = new
> TransformOutInterceptor();
> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
> http://something}Child1", ""));
> transformOutInterceptor.setOutAppendElements(Collections.singletonMap("{
> http://something}Child3", "{http://something}Child1=P1C1"));
> Here's the XML I end up with:
> <Container xmlns="http://something">
>     <Parent>
>         <Child2>P1C2</Child2>
>         <Child1>P1C1</Child1>
>         <Child3>P1C3</Child3>
>     </Parent>
>     <Parent>
>         <Child2>P2C3</Child2>
>     </Parent>
> </Container>
> So it looks like the setOutTransformElements got applied to both Parent
> elements, but the setOutAppendElements only got applied to the first. Is
> there a way to apply the setOutAppendElements to both Parent elements, each
> having a different transformed value? (i also though Child1 would end up
> after Child3, not before it)
>
> I couldn't figure out a way to do that so I started going the XSLT route.
> Here's what I ended up with:
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="2.0"  xpath-default-namespace="http://something">
>   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
>   <xsl:template match="node() | @*">
>     <xsl:copy>
>       <xsl:apply-templates select="node() | @*"/>
>     </xsl:copy>
>   </xsl:template>
>   <xsl:template match="Parent">
>     <xsl:copy>
>       <xsl:apply-templates select="Child3"/>
>       <xsl:apply-templates select="Child2"/>
>       <xsl:apply-templates select="Child1"/>
>     </xsl:copy>
>   </xsl:template>
> </xsl:stylesheet>
> It seems to work ok using this XSLT testing utility but it doesn't seem to
> do anything at all in CXF using:
> XSLTOutInterceptor outInterceptor = new
> XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null,
> "test.xsl");
> config.getOutInterceptors().add(outInterceptor);
>
> Is there something unsupported in that xslt that I'm trying to use?
> Many thanks for taking the time to help me with this, I really appreciate
> it.
> Greg
>
>
> On Fri, May 31, 2013 at 5:52 AM, Andrei Shakirin <as...@talend.com>
> wrote:
> Hi Greg,
>
> >Thank you for your input Andrei. I had been relying on
> LoggingOutInterceptor messages to see what the XML looked like so I thought
> maybe it was not accurate so I changed it to post the XML to a localhost
> >endpoint and rely on server side logging to see what the XML payload
> looked like. It confirmed the behavior I was seeing before.
> >Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
> seeing much different behavior now - it matches how you describe it should
> be working. So I guess it was a bug that was fixed at some >point.
> Obviously yes.
>
> >If I have to specify the element values when I call setInAppendElements,
> I guess I'll have to be manipulating the TransformOutInterceptor a lot more
> frequently than I had anticipated. Do I also need to handle >escaping of
> XML entity characters?
> I do not think that you should escape characters,
> XMLStreamWriter.writeCharacters() should do it per spec: "However the
> writeCharacters method is required to escape & , < and > For attribute
> values the writeAttribute method will escape the above characters plus " to
> ensure that all character content and attribute values are well formed".
>
> Regards,
> Andrei.
>
> From: Greg Barker [mailto:fletch@fletchowns.net]
> Sent: Freitag, 31. Mai 2013 04:56
> To: Andrei Shakirin
> Cc: users@cxf.apache.org
> Subject: Re: Specifying order of XML elements at runtime?
>
> Thank you for your input Andrei. I had been relying on
> LoggingOutInterceptor messages to see what the XML looked like so I thought
> maybe it was not accurate so I changed it to post the XML to a localhost
> endpoint and rely on server side logging to see what the XML payload looked
> like. It confirmed the behavior I was seeing before.
> Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
> seeing much different behavior now - it matches how you describe it should
> be working. So I guess it was a bug that was fixed at some point.
> If I have to specify the element values when I call setInAppendElements, I
> guess I'll have to be manipulating the TransformOutInterceptor a lot more
> frequently than I had anticipated. Do I also need to handle escaping of XML
> entity characters?
>
> On Wed, May 29, 2013 at 7:05 AM, Andrei Shakirin <as...@talend.com>
> wrote:
> Hi Greg,
>
> Sergei is in vacation this week, I will try to answer your question.
>
> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
> http://something}Child1", "")) should remove only Child1 element with all
> his children.
> Not sure why it results removing Parent children, are you sure with that
> test?
>
> What you basically need to delete and elements and insert it in different
> order is something like this:
>
> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
> http://something}Child2", ""));
> transformOutInterceptor.setInAppendElements(Collections.singletonMap("{
> http://something}Child1", "{http://something}Child2=Another Value"));
>
> If it not enough you can use XSLT Feature
> http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to
> your request/response.
>
> Other alternative is to create own interceptor, put it to POST_PROTOCOL
> phase and sort elements in message payload as you want.
>
> Regards,
> Andrei.
>
> > -----Original Message-----
> > From: Greg Barker [mailto:fletch@fletchowns.net]
> > Sent: Samstag, 25. Mai 2013 02:09
> > To: users@cxf.apache.org
> > Subject: Re: Specifying order of XML elements at runtime?
> >
> > Thanks for the quick reply Sergey!
> >
> > I'm having a bit a trouble with the suggested solution though, almost
> > certainly a pilot error on my part I assume.
> >
> > XML before:
> > <Container xmlns="http://something">
> >     <Parent>
> >         <Child1>Some Value</Child1>
> >         <Child2>Another Value</Child2>
> >     </Parent>
> > </Container>
> >
> > So I tried:
> > transformOutInterceptor.setOutDropElements(Collections.singletonList("{
> > http://something}Child1"));
> >
> > Which results in:
> > <Container xmlns="http://something">
> >     <Parent>
> >         Some Value
> >         <Child2>Another Value</Child2>
> >     </Parent>
> > </Container>
> >
> > Got rid of the element...but not the value. So I tried the "deep-drop"
> > described on that link:
> > transformOutInterceptor.setOutTransformElements(Collections.singletonM
> > ap("{
> > http://something}Child1", ""));
> >
> > Which resulted in:
> > <Container xmlns="http://something">
> >     <Parent/>
> > </Container>
> >
> > What am I screwing up? I basically just want to end up with:
> > <Container xmlns="http://something">
> >     <Parent>
> >         <Child2>Another Value</Child2>
> >         <Child1>Some Value</Child1>
> >     </Parent>
> >           </Container>
> >
> > Many Thanks!
> > Greg
> >
> >
> > On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
> > <sb...@gmail.com>wrote:
> >
> > > Hi
> > >
> > > On 23/05/13 22:02, Greg Barker wrote:
> > >
> > >> Hello -
> > >>
> > >> I'm using the Apache CXF WebClient for a project, and the REST API I
> > >> am interacting with has a requirement that XML elements are sent in a
> > >> specific order, and "correct" order can change depending on certain
> > >> settings that are not known at compile time.
> > >>
> > >> I've found that the XmlType.propOrder annotation allows me to specify
> > >> the order in which I want the XML elements to appear at compile time.
> > >> This works great. The problem is that I need to be able to change
> > >> this order at runtime, and I cannot figure out a way to do that
> > >> without resorting to ugly/hacky solutions that modify the annotation
> at
> > runtime.
> > >>
> > >> Is there an easy way to specify XML element order dynamically at
> > runtime?
> > >>
> > >>  Try Transformation feature:
> > >
> > > http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apa
> > > che.org/docs/transformationfeature.html>
> > >
> > > Use outDropElements and outAppendElements properties.
> > >
> > > Suppose you have the following produced by default:
> > > <request>
> > >   <a/>
> > >   <b/>
> > > </request>
> > >
> > > if needed, you can get <a/> dropped with outDropElements and then
> > > added immediately after <b/> with outAppendElements.
> > >
> > > If that has to be set up dynamically then add the feature or its
> > > interceptors from the code, similarly to
> > > http://cxf.apache.org/docs/**transformationfeature.html#**
> > > TransformationFeature-
> > **Configuringthefeaturefromtheco**de<http://cxf.
> > > apache.org/docs/transformationfeature.html#TransformationFeature-
> > Confi
> > > guringthefeaturefromthecode>
> > >
> > > HTH, Sergey
> > >
> > >  Thanks!
> > >> Greg
> > >>
> > >>
> > >
>
>

RE: Specifying order of XML elements at runtime?

Posted by Andrei Shakirin <as...@talend.com>.
Hi Greg,

>It seems to work ok using this XSLT testing utility but it doesn't seem to do anything at all in CXF using:
>XSLTOutInterceptor outInterceptor = new XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null, "test.xsl");
>config.getOutInterceptors().add(outInterceptor);

By default CXF XSLT feature uses Xalan TransformerFactory from JDK, which supports only XSLT 1.0.
You have two ways:
a) Rewrite your transformation using XSLT 1.0 (as a sample please look in http://svn.apache.org/repos/asf/cxf/trunk/systests/uncategorized/src/test/java/org/apache/cxf/systest/transform/feature/TransformFeatureTest.java  and http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/test/java/org/apache/cxf/feature/transform/XSLTInterceptorsTest.java )

b) Use other XSLT engine supporting XSLT 2.0 (for example SAXON http://saxon.sourceforge.net/)
I have never tested it, but TransformerFactory.newInstance() should obtain SAXON factory, if you specify following java option:
System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl") and have SAXON jars on your classpath;

Regards,
Andrei.

From: Greg Barker [mailto:fletch@fletchowns.net] 
Sent: Montag, 3. Juni 2013 20:27
To: Andrei Shakirin
Cc: users@cxf.apache.org
Subject: Re: Specifying order of XML elements at runtime?

How does the transformation feature work if there are more than 1 of the element being transformed?

For example:
<Container xmlns="http://something">
    <Parent>
        <Child1>P1C1</Child1>
        <Child2>P1C2</Child2>
        <Child3>P1C3</Child3>
    </Parent>
    <Parent>
        <Child1>P2C1</Child1>
        <Child2>P2C3</Child2>
    </Parent>
</Container>

After using the following:
TransformOutInterceptor transformOutInterceptor = new TransformOutInterceptor();
transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child1", ""));
transformOutInterceptor.setOutAppendElements(Collections.singletonMap("{http://something}Child3", "{http://something}Child1=P1C1"));
Here's the XML I end up with:
<Container xmlns="http://something">
    <Parent>
        <Child2>P1C2</Child2>
        <Child1>P1C1</Child1>
        <Child3>P1C3</Child3>
    </Parent>
    <Parent>
        <Child2>P2C3</Child2>
    </Parent>
</Container>
So it looks like the setOutTransformElements got applied to both Parent elements, but the setOutAppendElements only got applied to the first. Is there a way to apply the setOutAppendElements to both Parent elements, each having a different transformed value? (i also though Child1 would end up after Child3, not before it)

I couldn't figure out a way to do that so I started going the XSLT route. Here's what I ended up with:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="2.0"  xpath-default-namespace="http://something">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="Parent">
    <xsl:copy>
      <xsl:apply-templates select="Child3"/>
      <xsl:apply-templates select="Child2"/>
      <xsl:apply-templates select="Child1"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
It seems to work ok using this XSLT testing utility but it doesn't seem to do anything at all in CXF using:
XSLTOutInterceptor outInterceptor = new XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null, "test.xsl");
config.getOutInterceptors().add(outInterceptor);

Is there something unsupported in that xslt that I'm trying to use?
Many thanks for taking the time to help me with this, I really appreciate it.
Greg


On Fri, May 31, 2013 at 5:52 AM, Andrei Shakirin <as...@talend.com> wrote:
Hi Greg,

>Thank you for your input Andrei. I had been relying on LoggingOutInterceptor messages to see what the XML looked like so I thought maybe it was not accurate so I changed it to post the XML to a localhost >endpoint and rely on server side logging to see what the XML payload looked like. It confirmed the behavior I was seeing before.
>Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am seeing much different behavior now - it matches how you describe it should be working. So I guess it was a bug that was fixed at some >point.
Obviously yes.

>If I have to specify the element values when I call setInAppendElements, I guess I'll have to be manipulating the TransformOutInterceptor a lot more frequently than I had anticipated. Do I also need to handle >escaping of XML entity characters?
I do not think that you should escape characters, XMLStreamWriter.writeCharacters() should do it per spec: "However the writeCharacters method is required to escape & , < and > For attribute values the writeAttribute method will escape the above characters plus " to ensure that all character content and attribute values are well formed".

Regards,
Andrei.

From: Greg Barker [mailto:fletch@fletchowns.net]
Sent: Freitag, 31. Mai 2013 04:56
To: Andrei Shakirin
Cc: users@cxf.apache.org
Subject: Re: Specifying order of XML elements at runtime?

Thank you for your input Andrei. I had been relying on LoggingOutInterceptor messages to see what the XML looked like so I thought maybe it was not accurate so I changed it to post the XML to a localhost endpoint and rely on server side logging to see what the XML payload looked like. It confirmed the behavior I was seeing before.
Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am seeing much different behavior now - it matches how you describe it should be working. So I guess it was a bug that was fixed at some point.
If I have to specify the element values when I call setInAppendElements, I guess I'll have to be manipulating the TransformOutInterceptor a lot more frequently than I had anticipated. Do I also need to handle escaping of XML entity characters?

On Wed, May 29, 2013 at 7:05 AM, Andrei Shakirin <as...@talend.com> wrote:
Hi Greg,

Sergei is in vacation this week, I will try to answer your question.

transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child1", "")) should remove only Child1 element with all his children.
Not sure why it results removing Parent children, are you sure with that test?

What you basically need to delete and elements and insert it in different order is something like this:

transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child2", ""));
transformOutInterceptor.setInAppendElements(Collections.singletonMap("{http://something}Child1", "{http://something}Child2=Another Value"));

If it not enough you can use XSLT Feature http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to your request/response.

Other alternative is to create own interceptor, put it to POST_PROTOCOL phase and sort elements in message payload as you want.

Regards,
Andrei.

> -----Original Message-----
> From: Greg Barker [mailto:fletch@fletchowns.net]
> Sent: Samstag, 25. Mai 2013 02:09
> To: users@cxf.apache.org
> Subject: Re: Specifying order of XML elements at runtime?
>
> Thanks for the quick reply Sergey!
>
> I'm having a bit a trouble with the suggested solution though, almost
> certainly a pilot error on my part I assume.
>
> XML before:
> <Container xmlns="http://something">
>     <Parent>
>         <Child1>Some Value</Child1>
>         <Child2>Another Value</Child2>
>     </Parent>
> </Container>
>
> So I tried:
> transformOutInterceptor.setOutDropElements(Collections.singletonList("{
> http://something}Child1"));
>
> Which results in:
> <Container xmlns="http://something">
>     <Parent>
>         Some Value
>         <Child2>Another Value</Child2>
>     </Parent>
> </Container>
>
> Got rid of the element...but not the value. So I tried the "deep-drop"
> described on that link:
> transformOutInterceptor.setOutTransformElements(Collections.singletonM
> ap("{
> http://something}Child1", ""));
>
> Which resulted in:
> <Container xmlns="http://something">
>     <Parent/>
> </Container>
>
> What am I screwing up? I basically just want to end up with:
> <Container xmlns="http://something">
>     <Parent>
>         <Child2>Another Value</Child2>
>         <Child1>Some Value</Child1>
>     </Parent>
>           </Container>
>
> Many Thanks!
> Greg
>
>
> On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
> <sb...@gmail.com>wrote:
>
> > Hi
> >
> > On 23/05/13 22:02, Greg Barker wrote:
> >
> >> Hello -
> >>
> >> I'm using the Apache CXF WebClient for a project, and the REST API I
> >> am interacting with has a requirement that XML elements are sent in a
> >> specific order, and "correct" order can change depending on certain
> >> settings that are not known at compile time.
> >>
> >> I've found that the XmlType.propOrder annotation allows me to specify
> >> the order in which I want the XML elements to appear at compile time.
> >> This works great. The problem is that I need to be able to change
> >> this order at runtime, and I cannot figure out a way to do that
> >> without resorting to ugly/hacky solutions that modify the annotation at
> runtime.
> >>
> >> Is there an easy way to specify XML element order dynamically at
> runtime?
> >>
> >>  Try Transformation feature:
> >
> > http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apa
> > che.org/docs/transformationfeature.html>
> >
> > Use outDropElements and outAppendElements properties.
> >
> > Suppose you have the following produced by default:
> > <request>
> >   <a/>
> >   <b/>
> > </request>
> >
> > if needed, you can get <a/> dropped with outDropElements and then
> > added immediately after <b/> with outAppendElements.
> >
> > If that has to be set up dynamically then add the feature or its
> > interceptors from the code, similarly to
> > http://cxf.apache.org/docs/**transformationfeature.html#**
> > TransformationFeature-
> **Configuringthefeaturefromtheco**de<http://cxf.
> > apache.org/docs/transformationfeature.html#TransformationFeature-
> Confi
> > guringthefeaturefromthecode>
> >
> > HTH, Sergey
> >
> >  Thanks!
> >> Greg
> >>
> >>
> >


Re: Specifying order of XML elements at runtime?

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 03/06/13 19:27, Greg Barker wrote:
> How does the transformation feature work if there are more than 1 of the
> element being transformed?
>
> For example:
>
> <Container xmlns="http://something">
>      <Parent>
>          <Child1>P1C1</Child1>
>          <Child2>P1C2</Child2>
>          <Child3>P1C3</Child3>
>      </Parent>
>      <Parent>
>          <Child1>P2C1</Child1>
>          <Child2>P2C3</Child2>
>      </Parent>
> </Container>
>
> After using the following:
>
> TransformOutInterceptor transformOutInterceptor = new
> TransformOutInterceptor();
> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
> http://something}Child1", ""));
> transformOutInterceptor.setOutAppendElements(Collections.singletonMap("{
> http://something}Child3", "{http://something}Child1=P1C1"));
>
> Here's the XML I end up with:
>
> <Container xmlns="http://something">
>      <Parent>
>          <Child2>P1C2</Child2>
>          <Child1>P1C1</Child1>
>          <Child3>P1C3</Child3>
>      </Parent>
>      <Parent>
>          <Child2>P2C3</Child2>
>      </Parent>
> </Container>
>
> So it looks like the setOutTransformElements got applied to both Parent
> elements, but the setOutAppendElements only got applied to the first. Is
> there a way to apply the setOutAppendElements to both Parent elements, each
> having a different transformed value? (i also though Child1 would end up
> after Child3, not before it)
>
This feature can not follow complex rules at the moment, though in this 
case it may work but only of different parents have different 
namespaces, you'd just add two pairs into the transform map.

We may be able to support a simple XPath like matching in the future, 
but for now, in cases like this one, XSLT or manual DOM manipulation 
will do better


> I couldn't figure out a way to do that so I started going the XSLT route.
> Here's what I ended up with:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="2.0"  xpath-default-namespace="http://something">
>    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
>    <xsl:template match="node() | @*">
>      <xsl:copy>
>        <xsl:apply-templates select="node() | @*"/>
>      </xsl:copy>
>    </xsl:template>
>    <xsl:template match="Parent">
>      <xsl:copy>
>        <xsl:apply-templates select="Child3"/>
>        <xsl:apply-templates select="Child2"/>
>        <xsl:apply-templates select="Child1"/>
>      </xsl:copy>
>    </xsl:template>
> </xsl:stylesheet>
>
> It seems to work ok using this XSLT testing
> utility<http://xslttest.appspot.com/>but it doesn't seem to do
> anything at all in CXF using:
>
> XSLTOutInterceptor outInterceptor = new
> XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null,
> "test.xsl");
> config.getOutInterceptors().add(outInterceptor);
>
> Is there something unsupported in that xslt that I'm trying to use?
>
Likely to do with the actual set-up. Andrei will know,
Cheers, Sergey

> Many thanks for taking the time to help me with this, I really appreciate
> it.
>
> Greg
>
>
>
> On Fri, May 31, 2013 at 5:52 AM, Andrei Shakirin <as...@talend.com>wrote:
>
>> Hi Greg,
>>
>>> Thank you for your input Andrei. I had been relying on
>> LoggingOutInterceptor messages to see what the XML looked like so I thought
>> maybe it was not accurate so I changed it to post the XML to a localhost
>>> endpoint and rely on server side logging to see what the XML payload
>> looked like. It confirmed the behavior I was seeing before.
>>> Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
>> seeing much different behavior now - it matches how you describe it should
>> be working. So I guess it was a bug that was fixed at some >point.
>>
>> Obviously yes.
>>
>>> If I have to specify the element values when I call setInAppendElements,
>> I guess I'll have to be manipulating the TransformOutInterceptor a lot more
>> frequently than I had anticipated. Do I also need to handle >escaping of
>> XML entity characters?
>>
>> I do not think that you should escape characters,
>> XMLStreamWriter.writeCharacters() should do it per spec: "However the
>> writeCharacters method is required to escape & , < and > For attribute
>> values the writeAttribute method will escape the above characters plus " to
>> ensure that all character content and attribute values are well formed".
>>
>> Regards,
>> Andrei.
>>
>> From: Greg Barker [mailto:fletch@fletchowns.net]
>> Sent: Freitag, 31. Mai 2013 04:56
>> To: Andrei Shakirin
>> Cc: users@cxf.apache.org
>> Subject: Re: Specifying order of XML elements at runtime?
>>
>> Thank you for your input Andrei. I had been relying on
>> LoggingOutInterceptor messages to see what the XML looked like so I thought
>> maybe it was not accurate so I changed it to post the XML to a localhost
>> endpoint and rely on server side logging to see what the XML payload looked
>> like. It confirmed the behavior I was seeing before.
>> Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
>> seeing much different behavior now - it matches how you describe it should
>> be working. So I guess it was a bug that was fixed at some point.
>> If I have to specify the element values when I call setInAppendElements, I
>> guess I'll have to be manipulating the TransformOutInterceptor a lot more
>> frequently than I had anticipated. Do I also need to handle escaping of XML
>> entity characters?
>>
>> On Wed, May 29, 2013 at 7:05 AM, Andrei Shakirin <as...@talend.com>
>> wrote:
>> Hi Greg,
>>
>> Sergei is in vacation this week, I will try to answer your question.
>>
>> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
>> http://something}Child1", "")) should remove only Child1 element with all
>> his children.
>> Not sure why it results removing Parent children, are you sure with that
>> test?
>>
>> What you basically need to delete and elements and insert it in different
>> order is something like this:
>>
>> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
>> http://something}Child2", ""));
>> transformOutInterceptor.setInAppendElements(Collections.singletonMap("{
>> http://something}Child1", "{http://something}Child2=Another Value"));
>>
>> If it not enough you can use XSLT Feature
>> http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to
>> your request/response.
>>
>> Other alternative is to create own interceptor, put it to POST_PROTOCOL
>> phase and sort elements in message payload as you want.
>>
>> Regards,
>> Andrei.
>>
>>> -----Original Message-----
>>> From: Greg Barker [mailto:fletch@fletchowns.net]
>>> Sent: Samstag, 25. Mai 2013 02:09
>>> To: users@cxf.apache.org
>>> Subject: Re: Specifying order of XML elements at runtime?
>>>
>>> Thanks for the quick reply Sergey!
>>>
>>> I'm having a bit a trouble with the suggested solution though, almost
>>> certainly a pilot error on my part I assume.
>>>
>>> XML before:
>>> <Container xmlns="http://something">
>>>      <Parent>
>>>          <Child1>Some Value</Child1>
>>>          <Child2>Another Value</Child2>
>>>      </Parent>
>>> </Container>
>>>
>>> So I tried:
>>> transformOutInterceptor.setOutDropElements(Collections.singletonList("{
>>> http://something}Child1"));
>>>
>>> Which results in:
>>> <Container xmlns="http://something">
>>>      <Parent>
>>>          Some Value
>>>          <Child2>Another Value</Child2>
>>>      </Parent>
>>> </Container>
>>>
>>> Got rid of the element...but not the value. So I tried the "deep-drop"
>>> described on that link:
>>> transformOutInterceptor.setOutTransformElements(Collections.singletonM
>>> ap("{
>>> http://something}Child1", ""));
>>>
>>> Which resulted in:
>>> <Container xmlns="http://something">
>>>      <Parent/>
>>> </Container>
>>>
>>> What am I screwing up? I basically just want to end up with:
>>> <Container xmlns="http://something">
>>>      <Parent>
>>>          <Child2>Another Value</Child2>
>>>          <Child1>Some Value</Child1>
>>>      </Parent>
>>>            </Container>
>>>
>>> Many Thanks!
>>> Greg
>>>
>>>
>>> On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
>>> <sb...@gmail.com>wrote:
>>>
>>>> Hi
>>>>
>>>> On 23/05/13 22:02, Greg Barker wrote:
>>>>
>>>>> Hello -
>>>>>
>>>>> I'm using the Apache CXF WebClient for a project, and the REST API I
>>>>> am interacting with has a requirement that XML elements are sent in a
>>>>> specific order, and "correct" order can change depending on certain
>>>>> settings that are not known at compile time.
>>>>>
>>>>> I've found that the XmlType.propOrder annotation allows me to specify
>>>>> the order in which I want the XML elements to appear at compile time.
>>>>> This works great. The problem is that I need to be able to change
>>>>> this order at runtime, and I cannot figure out a way to do that
>>>>> without resorting to ugly/hacky solutions that modify the annotation
>> at
>>> runtime.
>>>>>
>>>>> Is there an easy way to specify XML element order dynamically at
>>> runtime?
>>>>>
>>>>>   Try Transformation feature:
>>>>
>>>> http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apa
>>>> che.org/docs/transformationfeature.html>
>>>>
>>>> Use outDropElements and outAppendElements properties.
>>>>
>>>> Suppose you have the following produced by default:
>>>> <request>
>>>>    <a/>
>>>>    <b/>
>>>> </request>
>>>>
>>>> if needed, you can get <a/> dropped with outDropElements and then
>>>> added immediately after <b/> with outAppendElements.
>>>>
>>>> If that has to be set up dynamically then add the feature or its
>>>> interceptors from the code, similarly to
>>>> http://cxf.apache.org/docs/**transformationfeature.html#**
>>>> TransformationFeature-
>>> **Configuringthefeaturefromtheco**de<http://cxf.
>>>> apache.org/docs/transformationfeature.html#TransformationFeature-
>>> Confi
>>>> guringthefeaturefromthecode>
>>>>
>>>> HTH, Sergey
>>>>
>>>>   Thanks!
>>>>> Greg
>>>>>
>>>>>
>>>>
>>
>>
>


Re: Specifying order of XML elements at runtime?

Posted by Greg Barker <fl...@fletchowns.net>.
How does the transformation feature work if there are more than 1 of the
element being transformed?

For example:

<Container xmlns="http://something">
    <Parent>
        <Child1>P1C1</Child1>
        <Child2>P1C2</Child2>
        <Child3>P1C3</Child3>
    </Parent>
    <Parent>
        <Child1>P2C1</Child1>
        <Child2>P2C3</Child2>
    </Parent>
</Container>

After using the following:

TransformOutInterceptor transformOutInterceptor = new
TransformOutInterceptor();
transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
http://something}Child1", ""));
transformOutInterceptor.setOutAppendElements(Collections.singletonMap("{
http://something}Child3", "{http://something}Child1=P1C1"));

Here's the XML I end up with:

<Container xmlns="http://something">
    <Parent>
        <Child2>P1C2</Child2>
        <Child1>P1C1</Child1>
        <Child3>P1C3</Child3>
    </Parent>
    <Parent>
        <Child2>P2C3</Child2>
    </Parent>
</Container>

So it looks like the setOutTransformElements got applied to both Parent
elements, but the setOutAppendElements only got applied to the first. Is
there a way to apply the setOutAppendElements to both Parent elements, each
having a different transformed value? (i also though Child1 would end up
after Child3, not before it)

I couldn't figure out a way to do that so I started going the XSLT route.
Here's what I ended up with:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0"  xpath-default-namespace="http://something">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="Parent">
    <xsl:copy>
      <xsl:apply-templates select="Child3"/>
      <xsl:apply-templates select="Child2"/>
      <xsl:apply-templates select="Child1"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

It seems to work ok using this XSLT testing
utility<http://xslttest.appspot.com/>but it doesn't seem to do
anything at all in CXF using:

XSLTOutInterceptor outInterceptor = new
XSLTOutInterceptor(Phase.PRE_STREAM, StaxOutInterceptor.class, null,
"test.xsl");
config.getOutInterceptors().add(outInterceptor);

Is there something unsupported in that xslt that I'm trying to use?

Many thanks for taking the time to help me with this, I really appreciate
it.

Greg



On Fri, May 31, 2013 at 5:52 AM, Andrei Shakirin <as...@talend.com>wrote:

> Hi Greg,
>
> >Thank you for your input Andrei. I had been relying on
> LoggingOutInterceptor messages to see what the XML looked like so I thought
> maybe it was not accurate so I changed it to post the XML to a localhost
> >endpoint and rely on server side logging to see what the XML payload
> looked like. It confirmed the behavior I was seeing before.
> >Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
> seeing much different behavior now - it matches how you describe it should
> be working. So I guess it was a bug that was fixed at some >point.
>
> Obviously yes.
>
> >If I have to specify the element values when I call setInAppendElements,
> I guess I'll have to be manipulating the TransformOutInterceptor a lot more
> frequently than I had anticipated. Do I also need to handle >escaping of
> XML entity characters?
>
> I do not think that you should escape characters,
> XMLStreamWriter.writeCharacters() should do it per spec: "However the
> writeCharacters method is required to escape & , < and > For attribute
> values the writeAttribute method will escape the above characters plus " to
> ensure that all character content and attribute values are well formed".
>
> Regards,
> Andrei.
>
> From: Greg Barker [mailto:fletch@fletchowns.net]
> Sent: Freitag, 31. Mai 2013 04:56
> To: Andrei Shakirin
> Cc: users@cxf.apache.org
> Subject: Re: Specifying order of XML elements at runtime?
>
> Thank you for your input Andrei. I had been relying on
> LoggingOutInterceptor messages to see what the XML looked like so I thought
> maybe it was not accurate so I changed it to post the XML to a localhost
> endpoint and rely on server side logging to see what the XML payload looked
> like. It confirmed the behavior I was seeing before.
> Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
> seeing much different behavior now - it matches how you describe it should
> be working. So I guess it was a bug that was fixed at some point.
> If I have to specify the element values when I call setInAppendElements, I
> guess I'll have to be manipulating the TransformOutInterceptor a lot more
> frequently than I had anticipated. Do I also need to handle escaping of XML
> entity characters?
>
> On Wed, May 29, 2013 at 7:05 AM, Andrei Shakirin <as...@talend.com>
> wrote:
> Hi Greg,
>
> Sergei is in vacation this week, I will try to answer your question.
>
> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
> http://something}Child1", "")) should remove only Child1 element with all
> his children.
> Not sure why it results removing Parent children, are you sure with that
> test?
>
> What you basically need to delete and elements and insert it in different
> order is something like this:
>
> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
> http://something}Child2", ""));
> transformOutInterceptor.setInAppendElements(Collections.singletonMap("{
> http://something}Child1", "{http://something}Child2=Another Value"));
>
> If it not enough you can use XSLT Feature
> http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to
> your request/response.
>
> Other alternative is to create own interceptor, put it to POST_PROTOCOL
> phase and sort elements in message payload as you want.
>
> Regards,
> Andrei.
>
> > -----Original Message-----
> > From: Greg Barker [mailto:fletch@fletchowns.net]
> > Sent: Samstag, 25. Mai 2013 02:09
> > To: users@cxf.apache.org
> > Subject: Re: Specifying order of XML elements at runtime?
> >
> > Thanks for the quick reply Sergey!
> >
> > I'm having a bit a trouble with the suggested solution though, almost
> > certainly a pilot error on my part I assume.
> >
> > XML before:
> > <Container xmlns="http://something">
> >     <Parent>
> >         <Child1>Some Value</Child1>
> >         <Child2>Another Value</Child2>
> >     </Parent>
> > </Container>
> >
> > So I tried:
> > transformOutInterceptor.setOutDropElements(Collections.singletonList("{
> > http://something}Child1"));
> >
> > Which results in:
> > <Container xmlns="http://something">
> >     <Parent>
> >         Some Value
> >         <Child2>Another Value</Child2>
> >     </Parent>
> > </Container>
> >
> > Got rid of the element...but not the value. So I tried the "deep-drop"
> > described on that link:
> > transformOutInterceptor.setOutTransformElements(Collections.singletonM
> > ap("{
> > http://something}Child1", ""));
> >
> > Which resulted in:
> > <Container xmlns="http://something">
> >     <Parent/>
> > </Container>
> >
> > What am I screwing up? I basically just want to end up with:
> > <Container xmlns="http://something">
> >     <Parent>
> >         <Child2>Another Value</Child2>
> >         <Child1>Some Value</Child1>
> >     </Parent>
> >           </Container>
> >
> > Many Thanks!
> > Greg
> >
> >
> > On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
> > <sb...@gmail.com>wrote:
> >
> > > Hi
> > >
> > > On 23/05/13 22:02, Greg Barker wrote:
> > >
> > >> Hello -
> > >>
> > >> I'm using the Apache CXF WebClient for a project, and the REST API I
> > >> am interacting with has a requirement that XML elements are sent in a
> > >> specific order, and "correct" order can change depending on certain
> > >> settings that are not known at compile time.
> > >>
> > >> I've found that the XmlType.propOrder annotation allows me to specify
> > >> the order in which I want the XML elements to appear at compile time.
> > >> This works great. The problem is that I need to be able to change
> > >> this order at runtime, and I cannot figure out a way to do that
> > >> without resorting to ugly/hacky solutions that modify the annotation
> at
> > runtime.
> > >>
> > >> Is there an easy way to specify XML element order dynamically at
> > runtime?
> > >>
> > >>  Try Transformation feature:
> > >
> > > http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apa
> > > che.org/docs/transformationfeature.html>
> > >
> > > Use outDropElements and outAppendElements properties.
> > >
> > > Suppose you have the following produced by default:
> > > <request>
> > >   <a/>
> > >   <b/>
> > > </request>
> > >
> > > if needed, you can get <a/> dropped with outDropElements and then
> > > added immediately after <b/> with outAppendElements.
> > >
> > > If that has to be set up dynamically then add the feature or its
> > > interceptors from the code, similarly to
> > > http://cxf.apache.org/docs/**transformationfeature.html#**
> > > TransformationFeature-
> > **Configuringthefeaturefromtheco**de<http://cxf.
> > > apache.org/docs/transformationfeature.html#TransformationFeature-
> > Confi
> > > guringthefeaturefromthecode>
> > >
> > > HTH, Sergey
> > >
> > >  Thanks!
> > >> Greg
> > >>
> > >>
> > >
>
>

RE: Specifying order of XML elements at runtime?

Posted by Andrei Shakirin <as...@talend.com>.
Hi Greg,

>Thank you for your input Andrei. I had been relying on LoggingOutInterceptor messages to see what the XML looked like so I thought maybe it was not accurate so I changed it to post the XML to a localhost >endpoint and rely on server side logging to see what the XML payload looked like. It confirmed the behavior I was seeing before.
>Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am seeing much different behavior now - it matches how you describe it should be working. So I guess it was a bug that was fixed at some >point.

Obviously yes.

>If I have to specify the element values when I call setInAppendElements, I guess I'll have to be manipulating the TransformOutInterceptor a lot more frequently than I had anticipated. Do I also need to handle >escaping of XML entity characters?

I do not think that you should escape characters, XMLStreamWriter.writeCharacters() should do it per spec: "However the writeCharacters method is required to escape & , < and > For attribute values the writeAttribute method will escape the above characters plus " to ensure that all character content and attribute values are well formed".

Regards,
Andrei.

From: Greg Barker [mailto:fletch@fletchowns.net] 
Sent: Freitag, 31. Mai 2013 04:56
To: Andrei Shakirin
Cc: users@cxf.apache.org
Subject: Re: Specifying order of XML elements at runtime?

Thank you for your input Andrei. I had been relying on LoggingOutInterceptor messages to see what the XML looked like so I thought maybe it was not accurate so I changed it to post the XML to a localhost endpoint and rely on server side logging to see what the XML payload looked like. It confirmed the behavior I was seeing before.
Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am seeing much different behavior now - it matches how you describe it should be working. So I guess it was a bug that was fixed at some point.
If I have to specify the element values when I call setInAppendElements, I guess I'll have to be manipulating the TransformOutInterceptor a lot more frequently than I had anticipated. Do I also need to handle escaping of XML entity characters?

On Wed, May 29, 2013 at 7:05 AM, Andrei Shakirin <as...@talend.com> wrote:
Hi Greg,

Sergei is in vacation this week, I will try to answer your question.

transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child1", "")) should remove only Child1 element with all his children.
Not sure why it results removing Parent children, are you sure with that test?

What you basically need to delete and elements and insert it in different order is something like this:

transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child2", ""));
transformOutInterceptor.setInAppendElements(Collections.singletonMap("{http://something}Child1", "{http://something}Child2=Another Value"));

If it not enough you can use XSLT Feature http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to your request/response.

Other alternative is to create own interceptor, put it to POST_PROTOCOL phase and sort elements in message payload as you want.

Regards,
Andrei.

> -----Original Message-----
> From: Greg Barker [mailto:fletch@fletchowns.net]
> Sent: Samstag, 25. Mai 2013 02:09
> To: users@cxf.apache.org
> Subject: Re: Specifying order of XML elements at runtime?
>
> Thanks for the quick reply Sergey!
>
> I'm having a bit a trouble with the suggested solution though, almost
> certainly a pilot error on my part I assume.
>
> XML before:
> <Container xmlns="http://something">
>     <Parent>
>         <Child1>Some Value</Child1>
>         <Child2>Another Value</Child2>
>     </Parent>
> </Container>
>
> So I tried:
> transformOutInterceptor.setOutDropElements(Collections.singletonList("{
> http://something}Child1"));
>
> Which results in:
> <Container xmlns="http://something">
>     <Parent>
>         Some Value
>         <Child2>Another Value</Child2>
>     </Parent>
> </Container>
>
> Got rid of the element...but not the value. So I tried the "deep-drop"
> described on that link:
> transformOutInterceptor.setOutTransformElements(Collections.singletonM
> ap("{
> http://something}Child1", ""));
>
> Which resulted in:
> <Container xmlns="http://something">
>     <Parent/>
> </Container>
>
> What am I screwing up? I basically just want to end up with:
> <Container xmlns="http://something">
>     <Parent>
>         <Child2>Another Value</Child2>
>         <Child1>Some Value</Child1>
>     </Parent>
>           </Container>
>
> Many Thanks!
> Greg
>
>
> On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
> <sb...@gmail.com>wrote:
>
> > Hi
> >
> > On 23/05/13 22:02, Greg Barker wrote:
> >
> >> Hello -
> >>
> >> I'm using the Apache CXF WebClient for a project, and the REST API I
> >> am interacting with has a requirement that XML elements are sent in a
> >> specific order, and "correct" order can change depending on certain
> >> settings that are not known at compile time.
> >>
> >> I've found that the XmlType.propOrder annotation allows me to specify
> >> the order in which I want the XML elements to appear at compile time.
> >> This works great. The problem is that I need to be able to change
> >> this order at runtime, and I cannot figure out a way to do that
> >> without resorting to ugly/hacky solutions that modify the annotation at
> runtime.
> >>
> >> Is there an easy way to specify XML element order dynamically at
> runtime?
> >>
> >>  Try Transformation feature:
> >
> > http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apa
> > che.org/docs/transformationfeature.html>
> >
> > Use outDropElements and outAppendElements properties.
> >
> > Suppose you have the following produced by default:
> > <request>
> >   <a/>
> >   <b/>
> > </request>
> >
> > if needed, you can get <a/> dropped with outDropElements and then
> > added immediately after <b/> with outAppendElements.
> >
> > If that has to be set up dynamically then add the feature or its
> > interceptors from the code, similarly to
> > http://cxf.apache.org/docs/**transformationfeature.html#**
> > TransformationFeature-
> **Configuringthefeaturefromtheco**de<http://cxf.
> > apache.org/docs/transformationfeature.html#TransformationFeature-
> Confi
> > guringthefeaturefromthecode>
> >
> > HTH, Sergey
> >
> >  Thanks!
> >> Greg
> >>
> >>
> >


Re: Specifying order of XML elements at runtime?

Posted by Greg Barker <fl...@fletchowns.net>.
Thank you for your input Andrei. I had been relying on
LoggingOutInterceptor messages to see what the XML looked like so I thought
maybe it was not accurate so I changed it to post the XML to a localhost
endpoint and rely on server side logging to see what the XML payload looked
like. It confirmed the behavior I was seeing before.

Then I tried bumping up my version number from 2.7.0 to 2.7.5 and I am
seeing much different behavior now - it matches how you describe it should
be working. So I guess it was a bug that was fixed at some point.

If I have to specify the element values when I call setInAppendElements, I
guess I'll have to be manipulating the TransformOutInterceptor a lot more
frequently than I had anticipated. Do I also need to handle escaping of XML
entity characters?


On Wed, May 29, 2013 at 7:05 AM, Andrei Shakirin <as...@talend.com>wrote:

> Hi Greg,
>
> Sergei is in vacation this week, I will try to answer your question.
>
> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
> http://something}Child1", "")) should remove only Child1 element with all
> his children.
> Not sure why it results removing Parent children, are you sure with that
> test?
>
> What you basically need to delete and elements and insert it in different
> order is something like this:
>
> transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
> http://something}Child2", ""));
> transformOutInterceptor.setInAppendElements(Collections.singletonMap("{
> http://something}Child1", "{http://something}Child2=Another Value"));
>
> If it not enough you can use XSLT Feature
> http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to
> your request/response.
>
> Other alternative is to create own interceptor, put it to POST_PROTOCOL
> phase and sort elements in message payload as you want.
>
> Regards,
> Andrei.
>
> > -----Original Message-----
> > From: Greg Barker [mailto:fletch@fletchowns.net]
> > Sent: Samstag, 25. Mai 2013 02:09
> > To: users@cxf.apache.org
> > Subject: Re: Specifying order of XML elements at runtime?
> >
> > Thanks for the quick reply Sergey!
> >
> > I'm having a bit a trouble with the suggested solution though, almost
> > certainly a pilot error on my part I assume.
> >
> > XML before:
> > <Container xmlns="http://something">
> >     <Parent>
> >         <Child1>Some Value</Child1>
> >         <Child2>Another Value</Child2>
> >     </Parent>
> > </Container>
> >
> > So I tried:
> > transformOutInterceptor.setOutDropElements(Collections.singletonList("{
> > http://something}Child1"));
> >
> > Which results in:
> > <Container xmlns="http://something">
> >     <Parent>
> >         Some Value
> >         <Child2>Another Value</Child2>
> >     </Parent>
> > </Container>
> >
> > Got rid of the element...but not the value. So I tried the "deep-drop"
> > described on that link:
> > transformOutInterceptor.setOutTransformElements(Collections.singletonM
> > ap("{
> > http://something}Child1", ""));
> >
> > Which resulted in:
> > <Container xmlns="http://something">
> >     <Parent/>
> > </Container>
> >
> > What am I screwing up? I basically just want to end up with:
> > <Container xmlns="http://something">
> >     <Parent>
> >         <Child2>Another Value</Child2>
> >         <Child1>Some Value</Child1>
> >     </Parent>
> >           </Container>
> >
> > Many Thanks!
> > Greg
> >
> >
> > On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
> > <sb...@gmail.com>wrote:
> >
> > > Hi
> > >
> > > On 23/05/13 22:02, Greg Barker wrote:
> > >
> > >> Hello -
> > >>
> > >> I'm using the Apache CXF WebClient for a project, and the REST API I
> > >> am interacting with has a requirement that XML elements are sent in a
> > >> specific order, and "correct" order can change depending on certain
> > >> settings that are not known at compile time.
> > >>
> > >> I've found that the XmlType.propOrder annotation allows me to specify
> > >> the order in which I want the XML elements to appear at compile time.
> > >> This works great. The problem is that I need to be able to change
> > >> this order at runtime, and I cannot figure out a way to do that
> > >> without resorting to ugly/hacky solutions that modify the annotation
> at
> > runtime.
> > >>
> > >> Is there an easy way to specify XML element order dynamically at
> > runtime?
> > >>
> > >>  Try Transformation feature:
> > >
> > > http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apa
> > > che.org/docs/transformationfeature.html>
> > >
> > > Use outDropElements and outAppendElements properties.
> > >
> > > Suppose you have the following produced by default:
> > > <request>
> > >   <a/>
> > >   <b/>
> > > </request>
> > >
> > > if needed, you can get <a/> dropped with outDropElements and then
> > > added immediately after <b/> with outAppendElements.
> > >
> > > If that has to be set up dynamically then add the feature or its
> > > interceptors from the code, similarly to
> > > http://cxf.apache.org/docs/**transformationfeature.html#**
> > > TransformationFeature-
> > **Configuringthefeaturefromtheco**de<http://cxf.
> > > apache.org/docs/transformationfeature.html#TransformationFeature-
> > Confi
> > > guringthefeaturefromthecode>
> > >
> > > HTH, Sergey
> > >
> > >  Thanks!
> > >> Greg
> > >>
> > >>
> > >
>

RE: Specifying order of XML elements at runtime?

Posted by Andrei Shakirin <as...@talend.com>.
Hi Greg,

Sergei is in vacation this week, I will try to answer your question.

transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child1", "")) should remove only Child1 element with all his children.
Not sure why it results removing Parent children, are you sure with that test?

What you basically need to delete and elements and insert it in different order is something like this:

transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{http://something}Child2", ""));
transformOutInterceptor.setInAppendElements(Collections.singletonMap("{http://something}Child1", "{http://something}Child2=Another Value"));

If it not enough you can use XSLT Feature http://cxf.apache.org/docs/xslt-feature.html to apply any XSLT script to your request/response.

Other alternative is to create own interceptor, put it to POST_PROTOCOL phase and sort elements in message payload as you want.

Regards,
Andrei.

> -----Original Message-----
> From: Greg Barker [mailto:fletch@fletchowns.net]
> Sent: Samstag, 25. Mai 2013 02:09
> To: users@cxf.apache.org
> Subject: Re: Specifying order of XML elements at runtime?
> 
> Thanks for the quick reply Sergey!
> 
> I'm having a bit a trouble with the suggested solution though, almost
> certainly a pilot error on my part I assume.
> 
> XML before:
> <Container xmlns="http://something">
>     <Parent>
>         <Child1>Some Value</Child1>
>         <Child2>Another Value</Child2>
>     </Parent>
> </Container>
> 
> So I tried:
> transformOutInterceptor.setOutDropElements(Collections.singletonList("{
> http://something}Child1"));
> 
> Which results in:
> <Container xmlns="http://something">
>     <Parent>
>         Some Value
>         <Child2>Another Value</Child2>
>     </Parent>
> </Container>
> 
> Got rid of the element...but not the value. So I tried the "deep-drop"
> described on that link:
> transformOutInterceptor.setOutTransformElements(Collections.singletonM
> ap("{
> http://something}Child1", ""));
> 
> Which resulted in:
> <Container xmlns="http://something">
>     <Parent/>
> </Container>
> 
> What am I screwing up? I basically just want to end up with:
> <Container xmlns="http://something">
>     <Parent>
>         <Child2>Another Value</Child2>
>         <Child1>Some Value</Child1>
>     </Parent>
>           </Container>
> 
> Many Thanks!
> Greg
> 
> 
> On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin
> <sb...@gmail.com>wrote:
> 
> > Hi
> >
> > On 23/05/13 22:02, Greg Barker wrote:
> >
> >> Hello -
> >>
> >> I'm using the Apache CXF WebClient for a project, and the REST API I
> >> am interacting with has a requirement that XML elements are sent in a
> >> specific order, and "correct" order can change depending on certain
> >> settings that are not known at compile time.
> >>
> >> I've found that the XmlType.propOrder annotation allows me to specify
> >> the order in which I want the XML elements to appear at compile time.
> >> This works great. The problem is that I need to be able to change
> >> this order at runtime, and I cannot figure out a way to do that
> >> without resorting to ugly/hacky solutions that modify the annotation at
> runtime.
> >>
> >> Is there an easy way to specify XML element order dynamically at
> runtime?
> >>
> >>  Try Transformation feature:
> >
> > http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apa
> > che.org/docs/transformationfeature.html>
> >
> > Use outDropElements and outAppendElements properties.
> >
> > Suppose you have the following produced by default:
> > <request>
> >   <a/>
> >   <b/>
> > </request>
> >
> > if needed, you can get <a/> dropped with outDropElements and then
> > added immediately after <b/> with outAppendElements.
> >
> > If that has to be set up dynamically then add the feature or its
> > interceptors from the code, similarly to
> > http://cxf.apache.org/docs/**transformationfeature.html#**
> > TransformationFeature-
> **Configuringthefeaturefromtheco**de<http://cxf.
> > apache.org/docs/transformationfeature.html#TransformationFeature-
> Confi
> > guringthefeaturefromthecode>
> >
> > HTH, Sergey
> >
> >  Thanks!
> >> Greg
> >>
> >>
> >

Re: Specifying order of XML elements at runtime?

Posted by Greg Barker <fl...@fletchowns.net>.
Thanks for the quick reply Sergey!

I'm having a bit a trouble with the suggested solution though, almost
certainly a pilot error on my part I assume.

XML before:
<Container xmlns="http://something">
    <Parent>
        <Child1>Some Value</Child1>
        <Child2>Another Value</Child2>
    </Parent>
</Container>

So I tried:
transformOutInterceptor.setOutDropElements(Collections.singletonList("{
http://something}Child1"));

Which results in:
<Container xmlns="http://something">
    <Parent>
        Some Value
        <Child2>Another Value</Child2>
    </Parent>
</Container>

Got rid of the element...but not the value. So I tried the "deep-drop"
described on that link:
transformOutInterceptor.setOutTransformElements(Collections.singletonMap("{
http://something}Child1", ""));

Which resulted in:
<Container xmlns="http://something">
    <Parent/>
</Container>

What am I screwing up? I basically just want to end up with:
<Container xmlns="http://something">
    <Parent>
        <Child2>Another Value</Child2>
        <Child1>Some Value</Child1>
    </Parent>
          </Container>

Many Thanks!
Greg


On Fri, May 24, 2013 at 3:36 AM, Sergey Beryozkin <sb...@gmail.com>wrote:

> Hi
>
> On 23/05/13 22:02, Greg Barker wrote:
>
>> Hello -
>>
>> I'm using the Apache CXF WebClient for a project, and the REST API I am
>> interacting with has a requirement that XML elements are sent in a
>> specific
>> order, and "correct" order can change depending on certain settings that
>> are not known at compile time.
>>
>> I've found that the XmlType.propOrder annotation allows me to specify the
>> order in which I want the XML elements to appear at compile time. This
>> works great. The problem is that I need to be able to change this order at
>> runtime, and I cannot figure out a way to do that without resorting to
>> ugly/hacky solutions that modify the annotation at runtime.
>>
>> Is there an easy way to specify XML element order dynamically at runtime?
>>
>>  Try Transformation feature:
>
> http://cxf.apache.org/docs/**transformationfeature.html<http://cxf.apache.org/docs/transformationfeature.html>
>
> Use outDropElements and outAppendElements properties.
>
> Suppose you have the following produced by default:
> <request>
>   <a/>
>   <b/>
> </request>
>
> if needed, you can get <a/> dropped with outDropElements and then added
> immediately after <b/> with outAppendElements.
>
> If that has to be set up dynamically then add the feature or its
> interceptors from the code, similarly to
> http://cxf.apache.org/docs/**transformationfeature.html#**
> TransformationFeature-**Configuringthefeaturefromtheco**de<http://cxf.apache.org/docs/transformationfeature.html#TransformationFeature-Configuringthefeaturefromthecode>
>
> HTH, Sergey
>
>  Thanks!
>> Greg
>>
>>
>

Re: Specifying order of XML elements at runtime?

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 23/05/13 22:02, Greg Barker wrote:
> Hello -
>
> I'm using the Apache CXF WebClient for a project, and the REST API I am
> interacting with has a requirement that XML elements are sent in a specific
> order, and "correct" order can change depending on certain settings that
> are not known at compile time.
>
> I've found that the XmlType.propOrder annotation allows me to specify the
> order in which I want the XML elements to appear at compile time. This
> works great. The problem is that I need to be able to change this order at
> runtime, and I cannot figure out a way to do that without resorting to
> ugly/hacky solutions that modify the annotation at runtime.
>
> Is there an easy way to specify XML element order dynamically at runtime?
>
Try Transformation feature:

http://cxf.apache.org/docs/transformationfeature.html

Use outDropElements and outAppendElements properties.

Suppose you have the following produced by default:
<request>
   <a/>
   <b/>
</request>

if needed, you can get <a/> dropped with outDropElements and then added 
immediately after <b/> with outAppendElements.

If that has to be set up dynamically then add the feature or its 
interceptors from the code, similarly to
http://cxf.apache.org/docs/transformationfeature.html#TransformationFeature-Configuringthefeaturefromthecode

HTH, Sergey

> Thanks!
> Greg
>