0

I have data like this -

<item>
    <name>Bob</name>
    <fav_food>pizza</fav_food>
    <key>{Salary}</key>
    <value>1000</value>
</item>

I want my output to look like this -

<item>
    <name>Bob</name>
    <fav_food>pizza</fav_food>
    <Salary>1000</Salary>
</item>

Edit, instead of just a value, if I had other tags only one of which is guaranteed to be nonempty like so, what is wrong with my transform? I'm using Sean's XSLT 1.0 transform as a source.

Input -

<item>
    <name>Bob</name>
    <fav_food>pizza</fav_food>
    <key>{Salary}</key>
    <value />
    <value2>1000</value2>
    <value3 />
</item>

Desired output -

<item>
    <name>Bob</name>
    <fav_food>pizza</fav_food>
    <Salary>1000</Salary>
</item>

My current transform -

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />  

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

<xsl:template match="key">
<xsl:element name="{substring-before(substring-after(.,'{'),'}')}"> 
    <xsl:choose>
        <xsl:when test="value != ''">
            <xsl:value-of select="following-sibling::value" />
        </xsl:when>
        <xsl:when test="value2 != ''">
            <xsl:value-of select="following-sibling::value2" />
        </xsl:when>
        <xsl:when test="value3 != ''">
            <xsl:value-of select="following-sibling::value3" />
        </xsl:when>
        </xsl:choose>
    </xsl:element> 
</xsl:template>
</xsl:stylesheet>

1 Answer 1

1

An XSLT 1.0 solution ...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />  

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

<xsl:template match="value" />

<xsl:template match="key">
 <xsl:element name="{substring-before(substring-after(.,'{'),'}')}"> 
   <xsl:value-of select="following-sibling::value" /> 
 </xsl:element> 
</xsl:template>

</xsl:stylesheet>

update

Here also is an XSLT 2 solution. This is untested.

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />  

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

<xsl:template match="attribute()|text()|comment()|processing-instruction()">
  <xsl:copy/>
</xsl:template>

<xsl:template match="value" />

<xsl:template match="key">
 <xsl:element name="{fn:replace(.,'^\{(.*)\}$','$1')}"> 
   <xsl:value-of select="following-sibling::value" /> 
 </xsl:element> 
</xsl:template>

</xsl:stylesheet>
6
  • Oh sorry, I forgot to state that there's no guarantee that value comes right after key....It might look like this <item><name>Bob</name><key>{Salary}</key><fav_food>pizza</fav_food><value>1000</value></item>
    – Narabhut
    Commented Jun 21, 2013 at 16:05
  • @Narabhut it will still work in that case. The value-of in the key template will take the first following-sibling value element even if there are other siblings with different names in between the key and the value. If it might be the case that the key comes after the value then use ../value instead of following-sibling::value. Commented Jun 21, 2013 at 16:17
  • I've updated the question with another problem I'm having. Thanks!
    – Narabhut
    Commented Jun 21, 2013 at 17:09
  • @Narabhut it would be better if you could make your second problem into a separate question. On SO each question can only have one accepted answer so it's clearer if you don't mix a new problem into an existing question that already has a correct answer. Commented Jun 21, 2013 at 19:33
  • @Narabhut, I look forward to your follow-up question. Be sure and specify which version of XSLT you are using (1.0, 2.0 or proto-3.0). Commented Jun 22, 2013 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.