Re: [xsl] xsl: parsing through specific child nodes

Subject: Re: [xsl] xsl: parsing through specific child nodes
From: "Mohit Anchlia" <mohitanchlia@xxxxxxxxx>
Date: Tue, 9 Sep 2008 09:01:51 -0700
Could somebody please help me understand why I am losing indentation.
Below are the complete details.

On Mon, Sep 8, 2008 at 12:57 PM, Mohit Anchlia <mohitanchlia@xxxxxxxxx> wrote:
> So I kind of got it working but need some help, I'll first post xml,
> xsl and output and then ask my questions:
>
> 1. XML
>
> <body>
> <ns2:getMessages xmlns:ns2="http://www.abc.com/wsdl/v";>
>         <ret>
>            <Msg>
>               <cid>103850015_0_1219420995471</cid>
>               <fid>41</fid>
>               <filing>IS</filing>
>               <State>PENDING</State>
>               <details>
>                  <Error>
>                     <Problem>Its pending</Problem>
>                  </Error>
>               </details>
>            </Msg>
>         </ret>
> </ns2:getMessages>
> </body>
>
>
> 2. xsl
>
> <?xml version="1.0"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0"
> exclude-result-prefixes="xmlns:ns2 ns2 xmlns">
> <xsl:output method="xml" indent="yes" />
> <xsl:variable name="file2" select="document('EFF')" />
> <xsl:key name='PENDING' match='statusMsg' use='./State'/>
> <xsl:template match="/">
>   <xsl:choose>
>    <xsl:when test="not(//State='PENDING')
>                and not(//State='SUCCEDED')">
>       <ret>
>          <xsl:copy-of select="//ret/*" />
>       </ret>
>    </xsl:when>
>    <xsl:when test="not($file2//State='PENDING')
>                and not($file2//State='SUCCEDED')">
>       <ret>
>          <xsl:copy-of select="$file2//ret/*" />
>       </ret>
>    </xsl:when>
>    <xsl:otherwise>
>          <xsl:for-each select="//ret/*">
>             <xsl:apply-templates select="*"/>
>          </xsl:for-each>
>    </xsl:otherwise>
>  </xsl:choose>
> </xsl:template>
> <xsl:template match="ret">
>       <xsl:apply-templates select="*"/>
> </xsl:template>
> <xsl:template match="*">
>  <xsl:element name="{name()}" namespace="{namespace-uri()}">
>   <xsl:choose>
>     <xsl:when test=".='PENDING'">
>             <xsl:text>1</xsl:text>
>     </xsl:when>
>   <xsl:otherwise>
>    <xsl:choose>
>     <xsl:when test="*">
>       <xsl:apply-templates select="*"/>
>     </xsl:when>
>     <xsl:otherwise>
>        <xsl:value-of select="." />
>     </xsl:otherwise>
>    </xsl:choose>
>   </xsl:otherwise>
>  </xsl:choose>
>  </xsl:element>
> </xsl:template>
> </xsl:stylesheet>
>
> 3. output
>
> <?xml version="1.0" encoding="UTF-8"?>
> <cid>103850015_0_1219420995471</cid>
> <fid>41</fid>
> <filing>IS</filing>
> <State>1</State>
> <details>
> <Error>
> <Problem>Its pending</Problem>
> </Error>
> </details>
>
> Questions:
>
> 1. But now I don't get <ret> and <Msg> tags, Msg tag in one xml could
> be Msg and other it could <CMsg> rest of the tags are same. How can I
> get them.
> 2. Also I am losing the indentation, it's all appearing on first
> column. I did get rid of ns2 though.
> 3. In above xsl what do I have to do if I want to make sure that it's
> the element node "State" whose child text node is "PENDING"?
>
> Also am I doing this xsl transformation correctly, in the sense that
> do you see any problems in terms of how it's done, efficiency etc.
>
> Thanks for your help.
> On Mon, Sep 8, 2008 at 12:31 PM, Michael Kay <mike@xxxxxxxxxxxx> wrote:
>> When you apply-templates to the ret element it does apply-templates on the
>> Msg element, which does xsl:copy-of the Msg element. It does not not do an
>> apply-templates on the State element so the code that replaces "PENDING"
>> with "1" is never activated.
>>
>> Michael Kay
>> http://www.saxonica.com/
>>
>>> -----Original Message-----
>>> From: Mohit Anchlia [mailto:mohitanchlia@xxxxxxxxx]
>>> Sent: 08 September 2008 18:45
>>> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
>>> Subject: Re: [xsl] xsl: parsing through specific child nodes
>>>
>>> Sorry I gave incorrect xml document:
>>>
>>> Here is the correct one:
>>>
>>> 1. xml document
>>>
>>> <body>
>>> <ns2:getMessages xmlns:ns2="http://www.abc.com/wsdl/v";>
>>>          <ret>
>>>             <Msg>
>>>                <cid>103850015_0_1219420995471</cid>
>>>                <fid>41</fid>
>>>                <filing>IS</filing>
>>>                <State>PENDING</State>
>>>             </Msg>
>>>          </ret>
>>> </ns2:getMessages>
>>> </body>
>>> 2. xsl file:
>>>
>>>
>>> <?xml version="1.0"?>
>>> <xsl:stylesheet
>>> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0"
>>>
>>> exclude-result-prefixes="xmlns:ns2 ns2 xmlns">
>>>
>>> <xsl:output method="xml" indent="yes" />
>>>
>>> <xsl:variable name="file2" select="document('EFF')" />
>>> <xsl:key name='PENDING' match='Msg' use='./State'/>
>>> <xsl:template match="/">
>>>   <xsl:choose>
>>>    <xsl:when test="not(//State='PENDING')
>>>                and not(//State='SUCCEDED')">
>>>       <ret>
>>>          <xsl:copy-of select="//ret/*" />
>>>       </ret>
>>>    </xsl:when>
>>>    <xsl:when test="not($file2//State='PENDING')
>>>                and not($file2//State='SUCCEDED')">
>>>       <ret>
>>>          <xsl:copy-of select="$file2//ret/*" />
>>>       </ret>
>>>    </xsl:when>
>>>    <xsl:otherwise>
>>>          <xsl:apply-templates select="//ret"/>
>>>    </xsl:otherwise>
>>>  </xsl:choose>
>>> </xsl:template>
>>> <xsl:template match="ret">
>>>       <xsl:apply-templates select="*"/>
>>>
>>> </xsl:template>
>>> <xsl:template match="*">
>>>
>>>  <xsl:copy>
>>>   <xsl:choose>
>>>     <xsl:when test="text()='PENDING'">
>>>             <xsl:text>1</xsl:text>
>>>     </xsl:when>
>>>   <xsl:otherwise>
>>>     <xsl:copy-of select="." />
>>>
>>>   </xsl:otherwise>
>>>  </xsl:choose>
>>>  </xsl:copy>
>>>
>>> </xsl:template>
>>> </xsl:stylesheet>
>>>
>>> 3. Output:
>>>
>>> <?xml version="1.0" encoding="UTF-8"?>
>>>
>>> <Msg xmlns:ns2="http://www.abc.com/wsdl/v";>
>>> <Msg>
>>>               <cid>103850015_0_1219420995471</cid>
>>>               <fid>41</fid>
>>>               <filing>IS</filing>
>>>               <State>PENDING</State>
>>>            </Msg>
>>> </Msg>
>>>
>>>
>>> On Mon, Sep 8, 2008 at 10:03 AM, Michael Kay
>>> <mike@xxxxxxxxxxxx> wrote:
>>> > In your match="/" template, the only apply-templates is to
>>> an element
>>> > called "ret". There is no element named ret in your source
>>> document.
>>> > Therefore the template rule with match="*" will never fire,
>>> therefore
>>> > the code that replaces "PENDING" by "1" will not be executed.
>>> >
>>> > Michael Kay
>>> > http://www.saxonica.com/
>>> >
>>> >> -----Original Message-----
>>> >> From: Mohit Anchlia [mailto:mohitanchlia@xxxxxxxxx]
>>> >> Sent: 08 September 2008 17:48
>>> >> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
>>> >> Subject: Re: [xsl] xsl: parsing through specific child nodes
>>> >>
>>> >> So I tried various things but it doesn't seem to be working.
>>> >> I'll give the complete information:
>>> >>
>>> >> 1. xml file:
>>> >> <?xml version="1.0" encoding="UTF-8"?> <Msg
>>> >> xmlns:ns2="http://www.abc.com/wsdl/v";>
>>> >> <Msg>
>>> >>                <cid>103850015_0_1219420995471</cid>
>>> >>                <fid>41</fid>
>>> >>                <filing>IS</filing>
>>> >>                <State>PENDING</State>
>>> >>             </Msg>
>>> >> </Msg>
>>> >>
>>> >> 2. xsl file:
>>> >>
>>> >> <?xml version="1.0"?>
>>> >> <xsl:stylesheet
>>> >> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0"
>>> >> exclude-result-prefixes="xmlns:ns2 ns2 xmlns"> <xsl:output
>>> >> method="xml" indent="yes" /> <xsl:variable name="file2"
>>> >> select="document('EFF')" /> <xsl:key name='PENDING'
>>> >> match='Msg' use='./State'/> <xsl:template match="/">
>>> >>    <xsl:choose>
>>> >>     <xsl:when test="not(//State='PENDING')
>>> >>                 and not(//State='SUCCEDED')">
>>> >>        <ret>
>>> >>           <xsl:copy-of select="//ret/*" />
>>> >>        </ret>
>>> >>     </xsl:when>
>>> >>     <xsl:when test="not($file2//State='PENDING')
>>> >>                 and not($file2//State='SUCCEDED')">
>>> >>        <ret>
>>> >>           <xsl:copy-of select="$file2//ret/*" />
>>> >>        </ret>
>>> >>     </xsl:when>
>>> >>     <xsl:otherwise>
>>> >>           <xsl:apply-templates select="//ret"/>
>>> >>     </xsl:otherwise>
>>> >>   </xsl:choose>
>>> >> </xsl:template>
>>> >> <xsl:template match="ret">
>>> >>        <xsl:apply-templates select="*"/> </xsl:template>
>>> >> <xsl:template match="*">  <xsl:copy>
>>> >>    <xsl:choose>
>>> >>      <xsl:when test="text()='PENDING'">
>>> >>              <xsl:text>1</xsl:text>
>>> >>      </xsl:when>
>>> >>    <xsl:otherwise>
>>> >>      <xsl:copy-of select="." />
>>> >>    </xsl:otherwise>
>>> >>   </xsl:choose>
>>> >>  </xsl:copy>
>>> >> </xsl:template>
>>> >> </xsl:stylesheet>
>>> >>
>>> >> 3. Output:
>>> >> <?xml version="1.0" encoding="UTF-8"?> <Msg
>>> >> xmlns:ns2="http://www.abc.com/wsdl/v";>
>>> >> <Msg>
>>> >>                <cid>103850015_0_1219420995471</cid>
>>> >>                <fid>41</fid>
>>> >>                <filing>IS</filing>
>>> >>                <State>PENDING</State>
>>> >>             </Msg>
>>> >> </Msg>
>>> >>
>>> >> 4.expected output:
>>> >>
>>> >> <?xml version="1.0" encoding="UTF-8"?> <Msg>
>>> >>                <cid>103850015_0_1219420995471</cid>
>>> >>                <fid>41</fid>
>>> >>                <filing>IS</filing>
>>> >>                <State>1</State>
>>> >>             </Msg>
>>> >> </Msg>
>>> >>
>>> >>
>>> >> First I don't understand how there are 2 Msg nodes. And
>>> >> second I wasn't able to get rid of namespace node by using
>>> >> <element> as suggested by Michael, it's still copying the
>>> >> namespace node.
>>> >> On Mon, Sep 8, 2008 at 6:52 AM, Mukul Gandhi
>>> >> <gandhi.mukul@xxxxxxxxx> wrote:
>>> >> > On Mon, Sep 8, 2008 at 1:16 AM, Mohit Anchlia
>>> >> <mohitanchlia@xxxxxxxxx> wrote:
>>> >> >> 1. So would above template mentioned by Mukul also output
>>> >> node HIJ ?
>>> >> >
>>> >> > I think, "outputting the node" is not the correct
>>> >> terminology. We can
>>> >> > copy the node to the result tree, or write something else to the
>>> >> > result tree, derived from the properties of the input nodes.
>>> >> >
>>> >> >>       <xsl:when test="local-name()="HIJ" and . = 'YYYYYY'">
>>> >> >
>>> >> > This statement will probably not compile, as I can see some
>>> >> misplaced quotes.
>>> >> >
>>> >> >
>>> >> >> 3. Currently I am using XSLT 1.0 and I am using JAXP which
>>> >> uses Xalan.
>>> >> >> How do I start using XSLT 2.0.
>>> >> >
>>> >> > You need to download an XSLT 2.0 processor, like Saxon and
>>> >> using it as
>>> >> > described in the documentation.
>>> >> >
>>> >> >> Would it just be matter of upping version in stylesheet node?
>>> >> >
>>> >> > No. version="2.0" is just a hint to the processor. You need
>>> >> to supply
>>> >> > the XSLT 2.0 stylesheet to a XSLT 2.0 processor like Saxon.
>>> >> >
>>> >> >
>>> >> > --
>>> >> > Regards,
>>> >> > Mukul Gandhi

Current Thread