Reputation: 1568
I'm trying to update some XSLT to accomodate a new XML input format. The new structure pretty much breaks my former template logic, but I'm trying to keep from having to rewrite the whole thing over.
Essentially, I'd like to grab the name of a template parameter, remove a prefix, and use the result in an <xsl:value-of/>
. For example:
<!-- calling location -->
<xsl:call-template name="myTemplate">
<xsl:with-param name="field" select="Name"/>
</xsl:call-template>
<!-- template to do the processing. -->
<xsl:template name="myTemplate">
<xsl:param name="field"/>
<xsl:variable name="fieldName" select="replace($field, 'Prefix', '')"/>
<xsl:value-of select="$fieldName"/>
</xsl:template>
The context.
This is more of a over all since I have been asked to provide both the essence of the question and the over all context. A simplified version of my stylesheet can bee seen below:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:variable name="delimiter" select="','" />
<xsl:variable name="newline" select="'
'" />
<xsl:template match="/root">
<xsl:apply-templates select="entry"/>
<xsl:apply-templates select="entry/Dependents"/>
</xsl:template>
<xsl:template match="entry">
<xsl:value-of select="Name"/>
<xsl:value-of select="$delimeter"/>
<xsl:value-of select="Address"/>
<xsl:value-of select="$delimeter"/>
<xsl:value-of select="Phone"/>
<xsl:value-of select="$newline"/>
</xsl:template>
<xsl:template match="entry/Dependents">
<xsl:call-template name="valueOrParentOrNone">
<xsl:with-param name="fieldValue" select="Name"/>
</xsl:call-template>
<xsl:value-of select="$delimeter"/>
<xsl:call-template name="valueOrParentOrNone">
<xsl:with-param name="fieldValue" select="Address"/>
</xsl:call-template>
<xsl:value-of select="$delimeter"/>
<xsl:call-template name="valueOrParentOrNone">
<xsl:with-param name="fieldValue" select="Phone"/>
</xsl:call-template>
<xsl:value-of select="$newline"/>
</xsl:template>
<xsl:template name="valueOrParentOrNone">
<xsl:param name="fieldValue"/>
<xsl:choose>
<!-- Use passed in node if exists -->
<xsl:when test="$fieldValue">
<xsl:value-of select="$fieldValue" />
</xsl:when>
<!-- Use parent node of the same name if exists -->
<xsl:when test="../$fieldName">
<xsl:value-of select="../$fieldName" />
</xsl:when>
<!-- Use "None" -->
<xsl:otherwise>
<xsl:text>"None"</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Original input XML:
<root>
<entry>
<Name>J. Smith</Name>
<Address>1123 XML Lane</Address>
<Phone>123-456-7890</Phone>
<Dependents>
<Name>S. Smith</Name>
<Address>1123 XML Lane</Address>
<Phone>123-456-0987</Phone>
</Dependents>
</entry>
<entry>
<Name>L. Hines</Name>
<Address>423 Programming Way</Address>
<Dependents>
<Name>P. Hines</Name>
</Dependents>
</entry>
</root>
New Input XML
<root>
<entry>
<Name>J. Smith</Name>
<Address>1123 XML Lane</Address>
<Phone>123-456-7890</Phone>
<DependentName>S. Smith</DependentName>
<DependentAddress>1123 XML Lane</DependentAddress>
<DependentPhone>123-456-0987</DependentPhone>
</entry>
<entry>
<Name>L. Hines</Name>
<Address>423 Programming Way</Address>
<DependentName>P. Hines</DependentName>
</entry>
</root>
You'll notice that not all of the values are available in either format above. I need to reuse the parent values when the dependent value doesn't exist. If neither exists, I need to use the value of "None". Input format changed so that the Dependents
sibling no longer exists. Instead, the children of the Dependents
has been raised to be siblings to the regular person values and are now a direct child of entry
.
Intended output.
"J. Smith","1123 XML Lane","123-456-7890"
"S. Smith","1123 XML Lane","123-456-0987"
"L. Hines","423 Programming Way",,
"P. Hines","423 Programming Way","None"
EDIT: Sorry for being confusing.
Upvotes: 0
Views: 1189
Reputation: 243469
Here is a complete transformation:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="my:f">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="entry">
<xsl:value-of select="string-join(
(string(Name), string(Address), string(Phone), ''[not(current()/Phone)]),
','),
'
'"/>
<xsl:apply-templates select="." mode="dependent"/>
</xsl:template>
<xsl:template match="entry" mode="dependent">
<xsl:value-of select="string-join(
(f:getValue(.,Name, DependentName), f:getValue(.,Address, DependentAddress),
f:getValue(.,Phone, DependentPhone)),','),
'
'"/>
</xsl:template>
<xsl:function name="f:getValue">
<xsl:param name="pParent" as="element()"/>
<xsl:param name="pChild" as="xs:string?"/>
<xsl:param name="pdepChild" as="xs:string?"/>
<xsl:variable name="vUsethis" select="($pdepChild, $pChild)[1]"/>
<xsl:sequence select="($vUsethis[.],'None')[1]"/>
</xsl:function>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<root>
<entry>
<Name>J. Smith</Name>
<Address>1123 XML Lane</Address>
<Phone>123-456-7890</Phone>
<DependentName>S. Smith</DependentName>
<DependentAddress>1123 XML Lane</DependentAddress>
<DependentPhone>123-456-0987</DependentPhone>
</entry>
<entry>
<Name>L. Hines</Name>
<Address>423 Programming Way</Address>
<DependentName>P. Hines</DependentName>
</entry>
</root>
the wanted, correct result is produced:
J. Smith,1123 XML Lane,123-456-7890
S. Smith,1123 XML Lane,123-456-0987
L. Hines,423 Programming Way,,
P. Hines,423 Programming Way,None
Upvotes: 1
Reputation: 243469
Just use:
<xsl:sequence select="($fieldValue[.], replace($fieldValue, 'Dependent', ''),'None')[1]"/>
Upvotes: 1
Reputation: 116982
IMHO, your best bet would be to rewrite your template as:
<xsl:template name="valueOrAltOrNone">
<xsl:param name="field"/>
<xsl:param name="alt-field"/>
<xsl:choose>
<xsl:when test="$field">
<xsl:value-of select="$field" />
</xsl:when>
<xsl:when test="$alt-field">
<xsl:value-of select="$alt-field" />
</xsl:when>
<xsl:otherwise>
<xsl:text>"None"</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
and call it as (for example):
<xsl:call-template name="valueOrAltOrNone">
<xsl:with-param name="field" select="DependentName"/>
<xsl:with-param name="alt-field" select="Name"/>
</xsl:call-template>
There is probably a shorter solution to do same, but I wanted to minimize the required changes.
Upvotes: 1