• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 575
  • Last Modified:

complex xsl transformation

Hi

i am trying to make xsl transformation  which also returns as xml.


<?xml version="1.0" encoding="utf-8"?>
<root>
 <header name="myname" id="999"/>
  <main>
      <facility_1>1</facility_1>      
      <services>
            <service>
                  <code>H</code>
                  <name>nam</name>
                  <assignedPersons>1,3</assignedPersons>
            </service>
            <service>
                  <code>U</code>
                  <name>UsedOne</name>
                  <assignedPersons>1,2</assignedPersons>
            </service>
      </services>
      <persons>
            <person>
                  <id>1</id>
                  <name>alex</name>
                  <setCode>0</setCode>
            <person>
            <person>
                  <id>2</id>
                  <name>sam</name>
                  <setCode>0</setCode>
            <person>
            <person>
                  <id>3</id>
                  <name>sam</name>
                  <setCode>0</setCode>
            <person>            
      </persons>
 </main>
</root>


Result looks as :


<?xml version="1.0" encoding="utf-8"?>
<root>
 <header name="myname" id="999"/>
  <main>
      <facility_1>1</facility_1>      
      <services>
            <service>
                  <code>H</code>
                  <name>nam</name>
                  <assignedPersons>1,3</assignedPersons>
            </service>
            <service>
                  <code>U</code>
                  <name>UsedOne</name>
                  <assignedPersons>1,2</assignedPersons>
            </service>
      </services>
      <persons>
            <person>
                  <id>1</id>
                  <name>alex</name>
                  <setCode>PQR</setCode>      <!--  here value is changed-->
            <person>
            <person>
                  <id>2</id>
                  <name>sam</name>
                  <setCode>0</setCode>
            <person>
            <person>
                  <id>3</id>
                  <name>sam</name>
                  <setCode>PQR</setCode>      <!--  here value is changed-->
            <person>            
      </persons>
 </main>
</root>




some sample xsl:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">  
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>

     
<xsl:template match="/ | @* | node()">
      <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
</xsl:template>

<xsl:template match="message/services/service">

      <xsl:choose>
            <xsl:when test="code='H'">
                  <xsl:copy>
                        <!--  DO SOMETHING-->                        
                  </xsl:copy>
            </xsl:when>
            <xsl:otherwise>
                  <xsl:copy>
                        <xsl:apply-templates select="@* | node()"/>
                  </xsl:copy>
            </xsl:otherwise>
      </xsl:choose>

</xsl:template>





I have to set the values of  "//persons/person/setCode"   based on following conditions.



conditions are:


in the xml document,
if there is any <service> node with child node <code> as 'H'

get the value of <assignedPersons>. (  in this case,value is "1,3")

means the service is assigned for //person/id='1' and //person/id='3' only.

set the value of <setCode> in "/root/main/persons/person[id='1']" as "PQR" and
                                            "/root/main/persons/person[id='3']" as "PQR"


if you have any questions,please mail me.


thank you,
vh

0
vihar123
Asked:
vihar123
  • 3
1 Solution
 
rdcproCommented:
Can there be more than one node where <code>H</code>?

If so, can an individual's id appear more than once?

IOW, is this possible:


     <services>
          <service>
               <code>H</code>
               <name>nam</name>
               <assignedPersons>1,3</assignedPersons>
          </service>
          <service>
               <code>H</code>
               <name>Somethingelse</name>
               <assignedPersons>1,2</assignedPersons>
          </service>
     </services>


Regards,
Mike Sharp
0
 
vihar123Author Commented:
Zero or one service with code "H" present in the xml.


0
 
rdcproCommented:
That makes it easier.  I'll work up an example today (it's mostly there).

Mike
0
 
rdcproCommented:
Ok, this XSLT will do it for you:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxsl="urn:schemas-microsoft-com:xslt">
      <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
      
      <xsl:key name="kCode" match="service" use="code"/>

      <xsl:template match="/ | @* | node()">
           <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
           </xsl:copy>
      </xsl:template>

      <xsl:template match="setCode">
            <xsl:copy>
                  <xsl:call-template name="tNodeParser">
                        <xsl:with-param name="pString" select="key('kCode', 'H')/assignedPersons"/>
                        <xsl:with-param name="pDelim">,</xsl:with-param>
                  </xsl:call-template>
            </xsl:copy>
      </xsl:template>


      <xsl:template name="tNodeParser">
            <xsl:param name="pString"/>
            <xsl:param name="pDelim"/>
            <xsl:choose>
                  <!-- If the current string starts with a "," character, drop it -->
                  <xsl:when test="starts-with($pString,$pDelim) and string-length($pString) &gt; 1">
                        <xsl:call-template name="tNodeParser">
                              <xsl:with-param name="pString" select="substring($pString, 2)"/>
                              <xsl:with-param name="pDelim" select="$pDelim"/>
                        </xsl:call-template>
                  </xsl:when>
                  <!-- This is for intermediate iterations, where there are still commas. Do something for this item -->
                  <xsl:when test="contains($pString,$pDelim)">
                        <xsl:choose>
                              <xsl:when test="substring-before($pString, $pDelim) = current()/preceding-sibling::id">PQR</xsl:when>
                              <xsl:otherwise>
                                    <xsl:call-template name="tNodeParser">
                                          <xsl:with-param name="pString" select="substring-after($pString,$pDelim)"/>
                                          <xsl:with-param name="pDelim" select="$pDelim"/>
                                    </xsl:call-template>
                              </xsl:otherwise>
                        </xsl:choose>
                  </xsl:when>
                  <!-- test the last item -->
                  <xsl:otherwise>
                        <xsl:if test="$pString = current()/preceding-sibling::id">PQR</xsl:if>
                  </xsl:otherwise>
            </xsl:choose>
      </xsl:template>
</xsl:stylesheet>


This uses a recursive template to process the <assignedPersons> child of the <service> node that has <code>H</code>.  I used an xsl:key to make it easy to get that node.  

The recursive template template looks at each comma separated value, and when it finds a match, it writes out "PQR".  

Regards,
Mike Sharp
0

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now