代码之家  ›  专栏  ›  技术社区  ›  davecardwell

使用XSLT查找给定参数集的节点

  •  2
  • davecardwell  · 技术社区  · 15 年前

    抱歉,标题“不知道怎么说”。

    基本上我有一些这样的XML:

    <countries>
        <country handle="bangladesh"/>
        <country handle="india"/>
        <country handle="pakistan"/>
    </countries>
    

    一些像这样的XSLT(不起作用):

    <xsl:template match="/countries">
        <xsl:param name="popular"/>        
        <xsl:apply-templates select="country[count($popular/country[@handle = current()/@handle]) &gt; 0]" />
    </xsl:template>    
    <xsl:template match="/countries/country">
        …
    </xsl:template>
    

    我想通过这样的热门目的地列表:

    <popular>
        <country handle="india"/>
        <country handle="pakistan"/>
    </popular>
    

    _to the/countries模板,并且只对$popular参数中的模板进行操作。目前,这根本无济于事。将选择器更改为country[true()]对它们都有效,因此至少我知道基本结构是正确的。

    有什么想法吗?我想我可能对目前的current()感到困惑。

    3 回复  |  直到 15 年前
        1
  •  1
  •   Robert Rossney    15 年前

    它比你想象的要简单得多:

    <xsl:template match="/">
      <popular>
        <xsl:copy-of select="/countries/country[@handle=$popular/country/@handle]"/>
      </popular>
    </xsl:template>
    

    编辑

    上面只显示了操作的原始XPath查询有什么问题。下面是一个完整的工作示例:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <xsl:param name="popular"/>
    
      <xsl:template match="/">
          <xsl:apply-templates select="/countries">
            <xsl:with-param name="popular" select="$popular"/>
          </xsl:apply-templates>
      </xsl:template>
    
      <xsl:template match="/countries">
        <xsl:param name="popular"/>
        <countries>
          <xsl:apply-templates select="country[@handle=$popular/country/@handle]"/>
        </countries>
      </xsl:template>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template> 
    
    </xsl:stylesheet>
    

    …还有一个叫它的程序:

    static void Main(string[] arguments)
    {
        XslCompiledTransform xslt = new XslCompiledTransform();
        xslt.Load("xsltfile1.xslt");
    
        XmlDocument d = new XmlDocument();
        d.LoadXml(@"
    <popular>
      <country handle='india'/>
      <country handle='xxx'/>
    </popular>");
    
        XsltArgumentList args = new XsltArgumentList();
        args.AddParam("popular", "", d.DocumentElement);
        xslt.Transform("xmlfile1.xml", args, Console.Out);
        Console.ReadKey();
    }
    
        2
  •  2
  •   Dimitre Novatchev    15 年前

    这个问题的解决方案简单明了 (不需要字符串编码或递归)。

    这种转变:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:param name="pPopular">
        <country handle="india"/>
        <country handle="pakistan"/>
     </xsl:param>
    
     <xsl:variable name="vPopular" 
      select="document('')/*/xsl:param[@name='pPopular']"/>
    
     <xsl:template match="node()|@*" name="identity">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="country">
      <xsl:if test="@handle = $vPopular/*/@handle">
       <xsl:call-template name="identity"/>
      </xsl:if>
     </xsl:template>
    </xsl:stylesheet>
    

    当应用于提供的XML文档时 :

    <countries>
        <country handle="bangladesh"/>
        <country handle="india"/>
        <country handle="pakistan"/>
    </countries>
    

    产生想要的、正确的结果 :

    <countries>
        <country handle="india"/>
        <country handle="pakistan"/>
    </countries>
    
        3
  •  0
  •   True Soft    15 年前

    下面介绍如何使用递归模板。必须以逗号分隔的列表形式传递热门目的地(如: "'india,pakistan,'" )

    <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/countries">
        <xsl:param name="popular" select="'india,pakistan,'" />
        <xsl:for-each select="country">
            <xsl:call-template name="print-country-from-list">
          <xsl:with-param name="pc" select="."/>
          <xsl:with-param name="listc" select="$popular"/>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>
    
    <xsl:template match="/countries/country">
       ... <xsl:value-of select="@handle"/>
    </xsl:template>
    
    <xsl:template name="print-country-from-list">
      <xsl:param name="pc"/>
      <xsl:param name="listc" select="''"/>
      <xsl:variable name="h" select="substring-before($listc, ',')"/>
      <xsl:if test="$h">
        <xsl:choose>
          <xsl:when test="$pc/@handle=$h">
            <xsl:apply-templates select="$pc" />
          </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="print-country-from-list">
            <xsl:with-param name="pc" select="$pc"/>
            <xsl:with-param name="listc" select="substring-after($listc, ',')"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
      </xsl:if>
    </xsl:template>
    
    </xsl:stylesheet>
    

    产量为两个国家。