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 <[email protected]>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:[email protected]]
> Sent: Freitag, 31. Mai 2013 04:56
> To: Andrei Shakirin
> Cc: [email protected]
> 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 <[email protected]>
> 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:[email protected]]
> > Sent: Samstag, 25. Mai 2013 02:09
> > To: [email protected]
> > 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
> > <[email protected]>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
> > >>
> > >>
> > >
>
>

Reply via email to