每个'的XSLT 1.0以'开头(长度可变) [英] XSLT 1.0 for-each 'starts-with' (with variable length)

查看:10
本文介绍了每个'的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#可能是最好(从性能角度来看)
假设1000个订单,200个推荐人...如果这会影响XSLT 1.0中的方法决策

有什么推荐/首选的|优化方法吗?

提前感谢😎

推荐答案

这里要理解的关键点是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>

这是一个相当笨拙的代码,但它很短并且可以工作。

这篇关于每个&#39;的XSLT 1.0以&#39;开头(长度可变)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆