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 > > >> > > >> > > > > >
