首页 文章

XSLT:在键函数中使用变量(续)

提问于
浏览
1

我有一个以下XML文件:

<titles> 
   <book title="XML Today" author="David Perry"/> 
   <book title="XML and Microsoft" author="David Perry"/> 
   <book title="XML Productivity" author="Jim Kim"/> 
   <book title="XSLT 1.0" author="Albert Jones"/> 
   <book title="XSLT 2.0" author="Albert Jones"/> 
   <book title="XSLT Manual" author="Jane Doe"/> 
</titles>

以@author'或'Jane'开头的@author消除元素的转换:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

  <xsl:output method="xml" indent="yes"/>

  <xsl:strip-space elements="*"/>

  <xsl:key name="author1-search" match="book[starts-with(@author, 'David')]" use="@title"/>
  <xsl:template match="book [key('author1-search', @title)]" />

  <xsl:key name="author2-search" match="book[starts-with(@author, 'Jane')]" use="@title"/>
  <xsl:template match="book [key('author2-search', @title)]" />

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

预期的结果将是以下XML文件:

<titles> 
   <book title="XML Productivity" author="Jim Kim"/> 
   <book title="XSLT 1.0" author="Albert Jones"/> 
   <book title="XSLT 2.0" author="Albert Jones"/> 
</titles>

在回答问题时,Dimitre Novatchev已经展示了使用迭代来显示由所选作者使用键编写的书籍的方法以及使用内联xsl参数的Exslt函数node-set()

<xsl:param name="pAuthors"> 
      <x>David Perry</x> 
      <x>Jane Doe</x> 
     </xsl:param>

是否可以应用此方法重写上面的转换,以便它使用pAuthors参数并只包含一个通用搜索键(而不是author1-search,author2-search等)?不支持XSLT 2.0和document()函数 .

提前谢谢,Leo

1 回答

  • 1

    我相信,从代码中的猜测来看,OP是如何使用XSLT键来帮助消除任何作者从一组作者写的书 .

    This transformation

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ext="http://exslt.org/common">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
        <xsl:param name="pAuthors">
            <x>David Perry</x>
            <x>Jane Doe</x>
        </xsl:param>
    
        <xsl:variable name="vParams" select=       "
          ext:node-set($pAuthors)/*"/>
    
      <xsl:key name="kBookByAuthor" match="book"
               use="@author"/>  
    
      <xsl:variable name="vBooksToExclude" select=
       "key('kBookByAuthor', $vParams)"/>
    
     <xsl:template match="node()|@*" name="identity">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>
    
     <xsl:template match="book">
      <xsl:if test="count(.|$vBooksToExclude) != count($vBooksToExclude)">
        <xsl:call-template name="identity"/>
      </xsl:if>
     </xsl:template>
    </xsl:stylesheet>
    

    when applied on the provided XML document

    <titles>
        <book title="XML Today" author="David Perry"/>
        <book title="XML and Microsoft" author="David Perry"/>
        <book title="XML Productivity" author="Jim Kim"/>
        <book title="XSLT 1.0" author="Albert Jones"/>
        <book title="XSLT 2.0" author="Albert Jones"/>
        <book title="XSLT Manual" author="Jane Doe"/>
    </titles>
    

    produces the wanted, correct result, in which any book that has an author from the provided set of authors (David Perry and Jane Doe), is skipped

    <titles>
       <book title="XML Productivity" author="Jim Kim"/>
       <book title="XSLT 1.0" author="Albert Jones"/>
       <book title="XSLT 2.0" author="Albert Jones"/>
    </titles>
    

    Explanation

    我们使用以下XPath表达式来确定节点 $n 是否不属于节点集 $s

    count($n | $s) != count($s)
    

    Final update

    正如OP所希望的那样,在这里我们排除从复制到输出的所有具有作者的书籍,其名字作为外部/全局参数中的许多值之一提供 . We still use a single key.

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ext="http://exslt.org/common">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
        <xsl:param name="pAuthors">
            <x>David</x>
            <x>Jane</x>
        </xsl:param>
    
        <xsl:variable name="vParams" select=       "
          ext:node-set($pAuthors)/*"/>
    
      <xsl:key name="kBookByAuthor" match="book"
               use="substring-before(@author, ' ')"/>
    
      <xsl:variable name="vBooksToExclude" select=
       "key('kBookByAuthor', $vParams)"/>
    
     <xsl:template match="node()|@*" name="identity">
         <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
         </xsl:copy>
     </xsl:template>
    
     <xsl:template match="book">
      <xsl:if test="count(.|$vBooksToExclude) != count($vBooksToExclude)">
        <xsl:call-template name="identity"/>
      </xsl:if>
     </xsl:template>
    </xsl:stylesheet>
    

    when this transformation is applied on the following XML document (另一位大卫作者补充道):

    <titles>
        <book title="XML Today" author="David Perry"/>
        <book title="XML and Microsoft" author="David Perry"/>
        <book title="Just example" author="David Masters"/>
        <book title="XML Productivity" author="Jim Kim"/>
        <book title="XSLT 1.0" author="Albert Jones"/>
        <book title="XSLT 2.0" author="Albert Jones"/>
        <book title="XSLT Manual" author="Jane Doe"/>
    </titles>
    

    produces the wanted, correct result

    <titles>
      <book title="XML Productivity" author="Jim Kim" />
      <book title="XSLT 1.0" author="Albert Jones" />
      <book title="XSLT 2.0" author="Albert Jones" />
    </titles>
    

相关问题