我正在尝试保留我的xsl DRY,因此我想为XML文档的2个部分调用相同的模板,这些部分碰巧是相同的复杂类型(ContactDetails和AltContactDetails)。给出以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<RootNode>
<Name>Bob</Name>
<ContactDetails>
<Address>
<Line1>1 High Street</Line1>
<Town>TownName</Town>
<Postcode>AB1 1CD</Postcode>
</Address>
<Email>test@test.com</Email>
</ContactDetails>
<AltContactDetails>
<Address>
<Line1>3 Market Square</Line1>
<Town>TownName</Town>
<Postcode>EF2 2GH</Postcode>
</Address>
<Email>bob@bob.com</Email>
</AltContactDetails>
</RootNode>
我写了一个XSL样式表,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<PersonsName>
<xsl:value-of select="RootNode/Name"/>
</PersonsName>
<xsl:call-template name="ContactDetails">
<xsl:with-param name="data"><xsl:value-of select="RootNode/ContactDetails"/></xsl:with-param>
<xsl:with-param name="elementName"><xsl:value-of select="'FirstAddress'"/></xsl:with-param>
</xsl:call-template>
<xsl:call-template name="ContactDetails">
<xsl:with-param name="data"><xsl:value-of select="RootNode/AltContactDetails"/></xsl:with-param>
<xsl:with-param name="elementName"><xsl:value-of select="'SecondAddress'"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="ContactDetails">
<xsl:param name="data"></xsl:param>
<xsl:param name="elementName"></xsl:param>
<xsl:element name="{$elementName}">
<FirstLine>
<xsl:value-of select="$data/Address/Line1"/>
</FirstLine>
<Town>
<xsl:value-of select="$data/Address/Town"/>
</Town>
<PostalCode>
<xsl:value-of select="$data/Address/Postcode"/>
</PostalCode>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
当我尝试运行样式表时,它向我抱怨我需要:
要在路径表达式中使用结果树片段,请使用exsl:node-set()或指定版本1.1
我不想转到1.1版。所以有谁知道如何让exsl:node-set()为上面的例子工作?
或者,如果有人知道将同一模板应用于2个不同部分的更好方法,那么这对我有帮助吗?
由于
戴夫
答案 0 :(得分:9)
你正在从错误的一端开始(错误的结局几乎总是:尝试将命令式编程范例应用于XSLT)。
通过模板匹配很容易做到。
<xsl:template match="RootNode">
<PersonsName>
<xsl:value-of select="Name"/>
</PersonsName>
<xsl:apply-templates select="ContactDetails|AltContactDetails" />
</xsl:template>
<xsl:template match="ContactDetails|AltContactDetails">
<xsl:copy>
<FirstLine>
<xsl:value-of select="Address/Line1"/>
</FirstLine>
<Town>
<xsl:value-of select="Address/Town"/>
</Town>
<PostalCode>
<xsl:value-of select="Address/Postcode"/>
</PostalCode>
</xsl:copy>
</xsl:template>
放下你必须告诉XSLT处理器做什么的想法(通过制作命名模板并调用它们,“命令式”)。
XSLT处理器选择要调用的模板。从根(/
)开始,它递归地检查它访问的每个节点的匹配模板。它独自遍历您的输入XML - 您唯一的工作就是为它提供匹配的模板,以便您以特殊方式处理这些节点。
您可以为需要特殊处理的节点提供自定义模板,并在XSLT处理器出现后调用它来信任它。您需要在模板中确保通过声明适当的<xsl:apply-templates />
继续遍历。
答案 1 :(得分:2)
为什么不制作模板
<xsl:template match="ContactDetails|AltContactDetails">
并进行测试以确定模板中的输出元素名称?