简体   繁体   中英

How to compare two comma-separated lists and removing matching values using XSLT 1.0

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.

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.

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.

I am an XSLT noob so can anyone help please?

Any help would be most appreciated

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM