如何比较两个以逗号分隔的列表并使用XSLT 1.0删除匹配的值

时间:2021-01-03 03:48:43

I have two variables which contain comma separated values:-

我有两个包含逗号分隔值的变量: -

  <xsl:variable name="Include-Cities" select="'London, Paris, Washington, Tokyo'"/>
  <xsl:variable name="Exclude-Cities" select="'Paris, Tokyo'"/>

I have a requirement to remove the values in $Include-Cities which match those found in $Exclude-Cities, so in a way I am subtracting those values from the $Include-Cities variable and outputting the result.

我要求删除$ Include-Cities中与$ Exclude-Cities中找到的值匹配的值,因此在某种程度上我从$ Include-Cities变量中减去这些值并输出结果。

I have looked around the web and found the following example which provides search and replace functionality and which works if the order of the cities in $Exclude-Cities matches the order in $Include-Cities, but fails if the order of values if different.

我查看了网页,发现以下示例提供搜索和替换功能,如果$ Exclude-Cities中的城市顺序与$ Include-Cities中的顺序匹配,则可以使用,但如果值的顺序不同则失败。

I am stuck as the values in both lists can change daily and i will never know what those values are, therefore i don't think performing a sort (if its possible) will work.

我被卡住,因为两个列表中的值都可以每天更改,我永远不会知道这些值是什么,因此我不认为执行排序(如果可能)将起作用。

The example i found:-

我找到的例子: -

<xsl:template name="replace-string">
    <xsl:param name="text"/>
    <xsl:param name="replace"/>
    <xsl:param name="with"/>
    <xsl:choose>
      <xsl:when test="contains($text,$replace)">
        <xsl:value-of select="substring-before($text,$replace)"/>
        <xsl:value-of select="$with"/>
        <xsl:call-template name="replace-string">
          <xsl:with-param name="text" select="substring-after($text,$replace)"/>
          <xsl:with-param name="replace" select="$replace"/>
          <xsl:with-param name="with" select="$with"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

Then i call the template using:-

然后我用以下方法调用模板: -

<xsl:call-template name="replace-string">
    <xsl:with-param name="text" select="$Include-Cities"/>
    <xsl:with-param name="replace" select="$Exclude-Cities" />
    <xsl:with-param name="with" select="''"/>
 </xsl:call-template>

I have also looked at examples of tokenizing the values and comparing that way but have had no joy whatsoever.

我还查看了对值进行标记并比较这种方式的例子,但没有任何乐趣。

I know there are string comparsion functions available in 2.0 but I am restricted to using XSLT 1.0.

我知道2.0中有可用的字符串比较函数,但我只能使用XSLT 1.0。

I am an XSLT noob so can anyone help please?

我是一个XSLT菜鸟,所以任何人都可以帮忙吗?

Any help would be most appreciated

非常感激任何的帮助

1 个解决方案

#1


0  

I have also looked at examples of tokenizing the values and comparing that way but have had no joy whatsoever.

我还查看了对值进行标记并比较这种方式的例子,但没有任何乐趣。

Tokenizing is the correct approach to take here. If your processor supports the EXSLT str:tokenize extension function, you could do:

令牌化是正确的方法。如果您的处理器支持EXSLT str:tokenize扩展功能,您可以执行以下操作:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="Include-Cities" select="'London, Paris, Washington, Tokyo'"/>
<xsl:variable name="Exclude-Cities" select="'Paris, Tokyo'"/>

<xsl:template match="/">
    <xsl:variable name="incl" select="str:tokenize($Include-Cities, ', ')"/>
    <xsl:variable name="excl" select="str:tokenize($Exclude-Cities, ', ')"/>
    <output>
        <xsl:copy-of select="$incl[not(.=$excl)]"/>
    </output>
</xsl:template>

and get:

Result

<?xml version="1.0" encoding="UTF-8"?>
<output>
  <token>London</token>
  <token>Washington</token>
</output>

Otherwise you would have to use a recursive named template to do tokenizing, convert the results to node-sets and then do the comparison as shown above.

否则,您必须使用递归命名模板进行标记化,将结果转换为节点集,然后进行比较,如上所示。

#1


0  

I have also looked at examples of tokenizing the values and comparing that way but have had no joy whatsoever.

我还查看了对值进行标记并比较这种方式的例子,但没有任何乐趣。

Tokenizing is the correct approach to take here. If your processor supports the EXSLT str:tokenize extension function, you could do:

令牌化是正确的方法。如果您的处理器支持EXSLT str:tokenize扩展功能,您可以执行以下操作:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="Include-Cities" select="'London, Paris, Washington, Tokyo'"/>
<xsl:variable name="Exclude-Cities" select="'Paris, Tokyo'"/>

<xsl:template match="/">
    <xsl:variable name="incl" select="str:tokenize($Include-Cities, ', ')"/>
    <xsl:variable name="excl" select="str:tokenize($Exclude-Cities, ', ')"/>
    <output>
        <xsl:copy-of select="$incl[not(.=$excl)]"/>
    </output>
</xsl:template>

and get:

Result

<?xml version="1.0" encoding="UTF-8"?>
<output>
  <token>London</token>
  <token>Washington</token>
</output>

Otherwise you would have to use a recursive named template to do tokenizing, convert the results to node-sets and then do the comparison as shown above.

否则,您必须使用递归命名模板进行标记化,将结果转换为节点集,然后进行比较,如上所示。