每个';的XSLT 1.0以';开头(长度可变) [英] XSLT 1.0 for-each 'starts-with' (with variable length)
本文介绍了每个';的XSLT 1.0以';开头(长度可变)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
发声思考,重新接近(ES🤔)
正在转换的输入集合(XML)记录(例如For-Each Order)。
使用XML‘Exclude’(引用集合)参数筛选出记录,
例如仅转换(For-Each Order)其中
(开始)当前订单/引用不等于引用集合中的任何引用。
为简单起见,请参阅订单输入示例
<Orders>
<Order number="1"> <!-- Include -->
<Reference>AB123</Reference>
</Order>
<Order number="2"> <!-- Exclude -->
<Reference>C3PO</Reference>
</Order>
</Orders>
和排除引用(可变长度)
<References>
<Reference>ABC</Reference>
<Reference>BC</Reference>
<Reference>AC</Reference>
<Reference>Z7</Reference>
</References>
- 我认为可能有几种方法可以做到这一点,但也许推荐一种/两种方法来提高性能...
- 考虑变量(不认为键会有帮助),不确定For-Each中的For-Each是否是一个选项,或者它将如何工作
- (我认为)的要点是使用以()开头的方法,其中要比较的字符数量各不相同……因此,某些C#可能是最好(从性能角度来看)
有什么推荐/首选的|优化方法吗?
提前感谢😎
推荐答案
这里要理解的关键点是starts-with()
函数将两个字符串作为其参数-而不是节点集。这意味着,虽然选择不是以特定字符串开头的所有订单非常容易,但使用:
Order[not(starts-with(Reference, $string)]
不是那么容易*颠倒视点并询问Order
是否以给定字符串中的任何一个开头?
这里需要记住的另一个要点是xsl:for-each
不是循环。它不允许退出条件,而且-对于我们的情况更重要的是-它不允许将一个迭代的结果传递给下一个迭代。由于我们希望在每次迭代中缩减订单的节点集,因此必须使用真正的递归工具:
XSLT 1.0
<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:strip-space elements="*"/>
<xsl:param name="path-to-references">References.xml</xsl:param>
<xsl:template match="/Orders">
<output>
<xsl:call-template name="exclude-orders">
<xsl:with-param name="orders" select="Order"/>
<xsl:with-param name="references" select="document($path-to-references)/References/Reference"/>
</xsl:call-template>
</output>
</xsl:template>
<xsl:template name="exclude-orders">
<xsl:param name="orders"/>
<xsl:param name="references"/>
<xsl:choose>
<xsl:when test="$references">
<!-- recursive call -->
<xsl:call-template name="exclude-orders">
<xsl:with-param name="orders" select="$orders[not(starts-with(Reference, $references[1]))]" />
<xsl:with-param name="references" select="$references[position() > 1]" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$orders"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
已添加:
(*)再想一想,您可以这样做:
<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:strip-space elements="*"/>
<xsl:param name="path-to-references">References.xml</xsl:param>
<xsl:template match="/Orders">
<output>
<xsl:for-each select="Order">
<xsl:if test="not(document($path-to-references)/References/Reference[starts-with(current()/Reference, .)])">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
这是一个相当笨拙的代码,但它很短并且可以工作。
这篇关于每个';的XSLT 1.0以';开头(长度可变)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文