gpt4 book ai didi

xslt - 如何创建模板以基于XSLT参数进行匹配

转载 作者:行者123 更新时间:2023-12-03 17:03:53 26 4
gpt4 key购买 nike

我正在尝试创建一个标准用途的XSLT,它将基于用户提供的XPATH表达式作为XSLT参数执行给定的任务。

也就是说,我需要这样的东西:

<xsl:template match="$paramContainingXPATH">
<!-- perform the task on the node(s) in the given xpath -->
</xsl:template>


例如,假设我有一些XML:

<xml>
<nodeA>whatever</nodeA>
<nodeB>whatever</nodeB>
<nodeC>whatever</nodeC>
<nodeD>whatever</nodeD>
<nodeE>whatever</nodeE>
</xml>


XSLT仅需要转换与提供的XPATH表达式匹配的一个或多个节点。因此,如果xslt参数为“ / xml / nodeC”,则它将处理nodeC。如果xslt参数为“ * [local-name()='nodeC'或local-name()='nodeE']”),则它将处理nodeC和nodeE。

这绝对适用于任何XML消息。也就是说,XSLT不能直接了解XML的内容。因此,它可以是原始XML或SOAP信封。

我猜想我可能需要抓住所有与xpath匹配的节点,然后遍历它们,调用命名模板,并对所有其他节点使用标准身份模板。

所有建议表示赞赏。

最佳答案

您无法使用参数来匹配模板-但您可以遍历树并将每个节点的路径与给定路径进行比较。这是一个简单的例子:

XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:param name="path" select="'/world/America/USA/California'"/>

<xsl:template match="/">
<root>
<xsl:apply-templates select="*"/>
</root>
</xsl:template>

<xsl:template match="*">
<xsl:variable name="path-to-me">
<xsl:for-each select="ancestor-or-self::node()">
<xsl:value-of select="name()" />
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:if test="$path=$path-to-me">
<xsl:call-template name="action"/>
</xsl:if>
<xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template name="action">
<return>
<xsl:value-of select="." />
</return>
</xsl:template>

</xsl:stylesheet>


应用于以下更雄心勃勃的测试输入:

<world>
<Europe>
<Germany>1</Germany>
<France>2</France>
<Italy>3</Italy>
</Europe>
<America>
<USA>
<NewYork>4</NewYork>
<California>5</California>
</USA>
<Canada>6</Canada>
</America>
</world>


结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<return>5</return>
</root>


通过将累积的路径作为递归模板的参数传递,可以使效率更高,因此每个节点仅需在链中添加自己的名称即可。

注意:


给定的路径必须是绝对路径;
谓词(包括位置谓词)和属性未在此实现。他们可能会付出更多的努力。
命名空间将被忽略(我看不到如何将XPath作为参数传递并仍然包含命名空间)。


如果处理器支持Evaluate()扩展功能,则可以放弃计算出的文本路径并测试交叉点。



编辑:

这是一个使用EXSLT dyn:evaluate()和set:intersection()的示例:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dyn="http://exslt.org/dynamic"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes="dyn set">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:param name="path" select="'/world/America/USA/California'"/>
<xsl:variable name="path-set" select="dyn:evaluate($path)" />

<xsl:template match="/">
<root>
<xsl:apply-templates select="*"/>
</root>
</xsl:template>

<xsl:template match="*">
<xsl:if test="set:intersection(. , $path-set)">
<xsl:call-template name="action"/>
</xsl:if>
<xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template name="action">
<return>
<xsl:value-of select="." />
</return>
</xsl:template>

</xsl:stylesheet>


请注意,这也适用于以下路径:

/world/America/USA/*[2]

//California

以及其他许多文本比较方法无法容纳的方法。

关于xslt - 如何创建模板以基于XSLT参数进行匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26978244/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com