如何在XSLT模板中获取参数的节点名称?

时间:2015-12-05 17:28:05

标签: xml xslt

我试图更新一些XSLT以容纳新的XML输入格式。新结构几乎打破了我以前的模板逻辑,但我试图避免重写整个过程。

基本上,我想获取模板参数的名称,删除前缀,并在<xsl:value-of/>中使用结果。例如:

<!-- 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>

背景。

自从我被要求提供问题的本质和整个背景以来,这更像是一个问题。我的样式表的简化版本如下所示:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:variable name="delimiter" select="','" />
    <xsl:variable name="newline" select="'&#xa;'" />

    <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>

原始输入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>

新输入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>

您会注意到并非所有值都以上述任何一种格式提供。当依赖值不存在时,我需要重用父值。如果两者都不存在,我需要使用&#34; None&#34;的值。输入格式已更改,以便Dependents兄弟不再存在。相反,Dependents的孩子已经成长为普通人价值观的兄弟姐妹,现在是entry的直接孩子。

预期输出。

"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"
编辑:很抱歉让人困惑。

3 个答案:

答案 0 :(得分:1)

恕我直言,您最好的选择是将模板重写为:

<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>

并将其称为(例如):

<xsl:call-template name="valueOrAltOrNone">
    <xsl:with-param name="field" select="DependentName"/>
    <xsl:with-param name="alt-field" select="Name"/>
</xsl:call-template>

可能有一个较短的解决方案,但我想尽量减少所需的更改。

答案 1 :(得分:1)

只需使用

  <xsl:sequence select="($fieldValue[.], replace($fieldValue, 'Dependent', ''),'None')[1]"/>

答案 2 :(得分:1)

这是一个完整的转型

<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)]),
       ','), 
      '&#xA;'"/>
   <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)),','), 
      '&#xA;'"/>
 </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>

在提供的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>

产生了想要的正确结果

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