2011-12-02 59 views
2

对两个xml文件进行分组。这是我在此处询问的一个演变: Groups two xml files like a sql group-by 给出的示例和Dimitre Solution计算不同的isbn值。 现在修改库XML有 mylibrary.xml:按照[2]

<library> 
    <book id="1" isbn="1"/> 
    <book id="2" isbn="1"/> 
    <book id="3" isbn="2"/> 
    <book id="4" isbn="4"/> 
    <book id="5" isbn="5"/> 
    <book id="6" isbn="4"/> 
    <book id="7" isbn="4"/> 
</library> 

而这一次,可用于: bookreference.xml:

<reference> 
    <book isbn="1"> 
     <category>SF</category> 
    </book> 
    <book isbn="2"> 
     <category>SF</category> 
    </book> 
    <book isbn="3"> 
     <category>SF</category> 
    </book> 
    <book isbn="4"> 
     <category>Comedy</category> 
    </book> 
    <book isbn="5"> 
     <category>Comedy</category> 
    </book> 
</reference> 

我想这本书的数字我有mylibrary'即使一些有相同的isbn',groupby category,使用xslt 1-0。

输出想要的东西:

SF : 3 book(s) 
Comedy : 4 book(s) 

我的XSLT在这里提出:Groups two xml files like a sql group-by工作正常,但“换每个”循环和扩展功能当然使用。 当然有更好的解决方案。

回答

1

同样一个问题非常好工作! (1)

这种变换,使用两个密钥实现充分效率

<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:key name="kBookByCat" match="book" 
      use="category"/> 

    <xsl:key name="kBookByIsbn" match="book" 
      use="@isbn"/> 

    <xsl:variable name="vDoc" select="/"/> 

    <xsl:variable name="vRef" select= 
    "document('file:///c:/temp/delete/reference.xml')"/> 

    <xsl:variable name="vMyIsbns" select="/*/*/@isbn"/> 

    <xsl:variable name="vResult"> 
     <xsl:apply-templates select="$vRef/*"/> 
    </xsl:variable> 

    <xsl:template match="/"> 
     <xsl:copy-of select="$vResult"/> 
    </xsl:template> 

    <xsl:template match= 
     "book[generate-id() 
      = 
      generate-id(key('kBookByCat', category)[1]) 
      ] 
     "> 
     <xsl:variable name="vBooksinCat" select= 
       "key('kBookByCat', category)"/> 

     <xsl:value-of select="category"/> : <xsl:text/> 
     <xsl:for-each select="$vDoc"> 
      <xsl:value-of select="count(key('kBookByIsbn',$vBooksinCat/@isbn))"/> 
     </xsl:for-each> 
     <xsl:text> book(s)&#xA;</xsl:text> 
    </xsl:template> 
    <xsl:template match="text()"/> 
</xsl:stylesheet> 

当上包含在文件mylibrary.xml提供的XML文档应用:

<library> 
    <book id="1" isbn="1"/> 
    <book id="2" isbn="1"/> 
    <book id="3" isbn="2"/> 
    <book id="4" isbn="4"/> 
    <book id="5" isbn="5"/> 
    <book id="6" isbn="4"/> 
    <book id="7" isbn="4"/> 
</library> 

并在C:\ temp \ delete \ reference.xml中提供了XML文档

<reference> 
    <book isbn="1"> 
     <category>SF</category> 
    </book> 
    <book isbn="2"> 
     <category>SF</category> 
    </book> 
    <book isbn="3"> 
     <category>SF</category> 
    </book> 
    <book isbn="4"> 
     <category>Comedy</category> 
    </book> 
    <book isbn="5"> 
     <category>Comedy</category> 
    </book> 
</reference> 

产生想要的,正确的输出

SF : 3 book(s) 
Comedy : 4 book(s) 
+0

看到你总是领先一步:P尽管由于某种原因,当我测试解决方案时,2个独特类别的模板匹配似乎并不奏效(vs2008),直到我将它移开,你会明白我的意思看看t答案之间的区别! – Treemonkey

+0

又是一个很好的答案,非常感谢,我像一个学生一样在问题和我的不良中花费了几个小时:当你在... 5分钟内完成时,从未找到解决方案? – Seb

+0

我还没有足够的声望(<100)来回答我的问题,但在3小时内,我将能够提出一个代码修改,以便在书籍计数= 0时不显示类别。 – Seb

1

修改迪米特里版本为这个

<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kBookByCat" match="book" use="category"/> 

<xsl:variable name="vRef" select="document('file:///c:/temp/delete/reference.xml')"/> 

<xsl:variable name="meh" select="*"/> 

<xsl:template match="/"> 
    <xsl:apply-templates select="$vRef/reference/book[generate-id()=generate-id(key('kBookByCat', category)[1])]" /> 
</xsl:template> 

<xsl:template match="book"> 
    <xsl:variable name="cat" select="category"/> 
    <xsl:value-of select="category"/> : <xsl:text/> 
    <xsl:variable name="isbns" select="$vRef/reference/book[category=$cat]/@isbn"/> 
    <xsl:value-of select="count($meh/book[@isbn=$isbns])"/> 
    <xsl:text> book(s)&#xA;</xsl:text> 
</xsl:template> 
0

中增加了很大的迪米特里响应,我提出以下不打印有0本书在MyLibrary设置书类别:

<xsl:variable name="catname" select="category"/> 
<xsl:for-each select="$vDoc"> 
    <xsl:variable name="cnt" select="count(key('kBookByIsbn',$vBooksinCat/@isbn))"/> 
    <xsl:if test="$cnt &gt; 0"> 
     <xsl:value-of select="$catname"/> : 
     <xsl:text/> 
     <xsl:value-of select="$cnt"/> 
     <xsl:text> book(s)&#xA;</xsl:text> 
    </xsl:if> 
</xsl:for-each>