Reputation: 299
I have an XML File:
<Items>
<Item Name="1" Value="test1"></Item>
<Item Name="2" Value="test2"></Item>
</Items>
What I want to transform with a predefined list:
<Items>
<Item Name="1">
<Value OldValue="test1" NewValue="TEST1" ></Value>
</Item>
<Item Name="2">
<Value OldValue="test2" NewValue="TEST2" ></Value>
</Item>
<Item Name="3">
<Value OldValue="" NewValue="TEST3" ></Value>
</Item>
</Items>
So, the value should be changed from the OldValue to the NewValue. If the Item is defined in this list and is not available in the input XML file (like Item Name="3") in this example, the Value should be set to EMPTY:
<Items>
<Item Name="1" Value="TEST1"></Item>
<Item Name="2" Value="TEST2"></Item>
<Item Name="3" Value="EMPTY"></Item>
</Items>
What I have so far:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://www.cdisc.org/ns/odm/v1.3"
xmlns="http://www.cdisc.org/ns/odm/v1.3">
<xsl:strip-space elements="*" />
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" name="xml" />
<xsl:variable name="Items">
<Item Name="1">
<Value OldValue="test1" NewValue="TEST1" ></Value>
</Item>
<Item Name="2">
<Value OldValue="test2" NewValue="TEST2" ></Value>
</Item>
<Item Name="3">
<Value OldValue="test3" NewValue="TEST3" ></Value>
</Item>
</xsl:variable>
<xsl:template match="Items">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="Item">
<xsl:copy>
<xsl:attribute name="Value">
<xsl:choose>
<xsl:when >
<!-- check if Item is defined in Items and missing here -->
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$Items/Item[@Name=current()/@Name]/Value[@OldValue = current()/@Value]/@NewValue"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:copy-of select="@*[name()!= 'Value']" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
What I'm missing is an idea how to detect if an item is missing or not in the when clause. Can anyone give me a hint how to solve this? Maybe with a function?
Upvotes: 2
Views: 911
Reputation: 117043
Would something like this work for you?
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="item" match="Item" use="@Name" />
<xsl:variable name="xml" select="/" />
<xsl:variable name="Items">
<Item Name="1">
<Value OldValue="test1" NewValue="TEST1" ></Value>
</Item>
<Item Name="2">
<Value OldValue="test2" NewValue="TEST2" ></Value>
</Item>
<Item Name="3">
<Value OldValue="test3" NewValue="TEST3" ></Value>
</Item>
</xsl:variable>
<xsl:template match="/">
<root>
<xsl:for-each select="$Items/Item">
<Item Name="{@Name}" Value="{Value/@NewValue}">
<xsl:if test="not(key('item', @Name, $xml))">
<xsl:attribute name="Value">EMPTY</xsl:attribute>
</xsl:if>
</Item>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
Applied to your input example, the result is:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<Item Name="1" Value="TEST1"/>
<Item Name="2" Value="TEST2"/>
<Item Name="3" Value="EMPTY"/>
</root>
Upvotes: 1