XSLT 2.0:如何在两个序列之间使用 starts-with 函数?

XSLT 2.0: How can I use the starts-with function between two sequences?

我收到了一系列代码,我不知道哪些是“通配符”代码,哪些是完整代码。在我下面的示例中,代码“1234”是“通配符”代码,代码“5678”是完整代码。因此,我需要 xslt,它将 return 所有代码以 1234 开头或等于代码 5678 的过程。我知道 starts-with xslt 函数不能应用于序列。我尝试了 for-each 的多种变体,但都无济于事。有什么建议吗?

对不起,如果我不清楚,我不知道哪些代码是通配符,哪些是完整的。 “starts-with”函数将匹配以指定代码开头的过程代码以及与指定代码完全匹配的过程代码。我提供的代码是我收到的示例,1234 和 5678 都可以是通配符或都不是,等等...

代码 XML:

<Codes>
  <Code>1234</Code>
  <Code>5678</Code>
</Codes>

程序XML:

<Procedures>
  <Procedure>
    <Code>12345678</Code>
  </Procedure>
  <Procedure>
    <Code>5678</Code>
  </Procedure>
  <Procedure>
    <Code>91011</Code>
  </Procedure>
  <Procedure>
    <Code>12348765</Code>
  </Procedure>
</Procedures>

我需要return的是:

<Procedures>
  <Procedure>
    <Code>12345678</Code>
  </Procedure>
  <Procedure>
    <Code>5678</Code>
  </Procedure>
  <Procedure>
    <Code>12348765</Code>
  </Procedure>
</Procedures>

我不确定我是否完全理解您正在寻找的内容,但我认为这应该可行。

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

  <xsl:output method="xml" indent="yes"/>
  
  <xsl:variable name="inputCodes">
    <Codes>
      <Code>1234</Code>
      <Code>5678</Code>
    </Codes>
  </xsl:variable>
  
  <xsl:variable name="wildcard" select="$inputCodes/Codes/Code[1]"/>
  <xsl:variable name="complete" select="$inputCodes/Codes/Code[2]"/>
  
  <xsl:template match="Procedure[not(Code=$complete or starts-with(Code,$wildcard))]"/>
  
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

看到它在这里工作:https://xsltfiddle.liberty-development.net/a9HjZE

实现这一点的一种方法是 XSLT-2.0 样式表(具有限制的第一个文件名为 Codes.xml):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
  <xsl:variable name="wildcard" select="doc('Codes.xml')/Codes/Code[1]" />
  <xsl:variable name="complete" select="doc('Codes.xml')/Codes/Code[2]" />
  <xsl:strip-space elements="*" />

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Procedure" />
    
    <xsl:template match="Procedure[starts-with(Code,$wildcard) or Code=$complete]">
        <xsl:copy-of select="." />
    </xsl:template>
    
</xsl:stylesheet>

它的输出符合预期:

<Procedures>
    <Procedure>
        <Code>12345678</Code>
    </Procedure>
    <Procedure>
        <Code>5678</Code>
    </Procedure>
    <Procedure>
        <Code>12348765</Code>
    </Procedure>
</Procedures>

以上样式表为“通配符”和“完整”字符串值定义了两个变量。然后它使用身份模板复制所有其他元素并省略所有Procedure元素,除了在最后一个模板中确认的实现所需条件的元素。

我将忽略完整代码和“通配符”代码之间令人困惑的区别,并专注于根本问题,即:当您有多个起始字符串要检查时如何应用 starts-with() 函数反对。

IOW,我们正在寻找一种方法 select Procedure 节点 Codeany 中列出的代码开头=26=].

这可以简单地通过反转角度来完成:

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:param name="path-to-codes" select="'Codes.xml'"/>

<xsl:template match="/Procedures">
    <xsl:copy>
        <xsl:for-each select="Procedure">
            <xsl:variable name="current-code" select="Code" />
            <xsl:if test="document($path-to-codes)/Codes/Code[starts-with($current-code, .)]">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>