Safi Muktadar Abdul
Safi Muktadar Abdul

Reputation: 45

XSLT 2.0 Replace all occurrences of 'true/false' from xml with 'yes/no'

I have an xml document with bunch of nodes in which certain nodes are true and false as values. I am working on a xslt to transform that xml document into a comma (or '&') separated string. I want to replace all values that are true false to yes and no without having to do xsl:when true then yes otherwise no, because there are a bunch of them. Is there a way i can do that? Any help is highly appreciated.

XML:

<MainNode>
<P1>
<someNode/>
<P2>
    <History>
        <MedicalHistory>                
            <Medication>true</Medication>
            <Medical_Treatment>true</Medical_Treatment>
            <Hospital>false</Hospital>
            <Comments>some Comment</Comments>
       </MedicalHistory>
    </History>
    <Info>
       <Name>Sam</Name>
       <Gender>male</Gender>
       <Married>false</Married>
    </Info>
</P2></P1></MainNode>

XSLT:

xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:text>name=</xsl:text>
    <xsl:value-of select="//MainNode/P1/P2/Info/Name"/>
    <xsl:text>&amp;Gender=</xsl:text>
    <xsl:value-of select="//MainNode/P1/P2/Info/Gender"/>
    <xsl:text>&amp;Married=</xsl:text>
    <xsl:value-of select="//MainNode/P1/P2/Info/Married"/>
    <xsl:text>&amp;Comments=</xsl:text>
    <xsl:value-of select="//MainNode/P1/P2/History/Comments"/>
    <xsl:text>&amp;Medication=</xsl:text>
    <xsl:value-of select="//MainNode/P1/P2/History/Medication"/>
   </xsl:template>
</xsl:stylesheet>

Output: name=Sam&Gender=Male&Married=false&Comments=some Comments&Medication=true

I would want the output to have all the 'true' and 'false' to be replaced by 'yes' and 'no' Output: name=Sam&Gender=Male&Married=no&Comments=some Comments&Medication=yes

Right now iam following this approach in the xslt

xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:text>name=</xsl:text>
    <xsl:value-of select="//MainNode/P1/P2/Info/Name"/>
    <xsl:text>&amp;Gender=</xsl:text>
    <xsl:choose>
        <xsl:when test="//MainNode/P1/P2/Info/Gender = 'true'">
           <xsl:text>yes</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>no</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
    <xsl:text>&amp;Married=</xsl:text>
    <xsl:value-of select="//MainNode/P1/P2/Info/Married"/>
    <xsl:text>&amp;Comments=</xsl:text>
    <xsl:value-of select="//MainNode/P1/P2/History/Comments"/>
    <xsl:text>&amp;Medication=</xsl:text>
    xsl:choose>
        <xsl:when test="//MainNode/P1/P2/History/Medication = 'true'">
           <xsl:text>yes</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>no</xsl:text>
        </xsl:otherwise>
    </xsl:choose>        
   </xsl:template>
</xsl:stylesheet>

Of course the main xslt and xml are quite big and complicated that result in a bunch of 'when/other' blocks

Please help me with this. Not very experienced with xslt. thanks!

Upvotes: 2

Views: 545

Answers (2)

Michael Kay
Michael Kay

Reputation: 163625

I would use a function:

<xsl:value-of select="my:bool(//MainNode/P1/P2/Info/Gender)"/>

then

<xsl:function name="my:bool" as="xs:string">
  <xsl:param name="s" as="xs:string">
  <xsl:sequence select="if ($s='true') then 'yes' else 'no'"/>
</xsl:function>

Note also that XSLT 3.0 allows you:

<xsl:for-each select="//MainNode/P1/P2/Info">
  <xsl:text>name={Name}&amp;Gender={my:bool(Gender)}&amp;Married={my:bool(Married)}</xsl:text>
</xsl:for-each>
<xsl:for-each select="//MainNode/P1/P2/History">
  <xsl:text>comments={Comments}&amp;Medication={my:bool(Medication)}</xsl:text>
</xsl:for-each>

Upvotes: 1

Siebe Jongebloed
Siebe Jongebloed

Reputation: 4870

There are a lot of ways to solve this. I.e. add these two templates to your xslt:

  <xsl:template match="text()[.='true']" >
    <xsl:text>yes</xsl:text>
  </xsl:template>
    
  <xsl:template match="text()[.='false']" >
    <xsl:text>no</xsl:text>
  </xsl:template>

And then in stead of

  <xsl:choose>
    <xsl:when test="//MainNode/P1/P2/Info/Gender = 'true'">
      <xsl:text>yes</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:text>no</xsl:text>
    </xsl:otherwise>
  </xsl:choose>   

Do:

<xsl:apply-templates select="//MainNode/P1/P2/Info/Gender/text()"/>

Upvotes: 3

Related Questions