2010-12-14 105 views
2

我寫xsl將xml轉換爲raport版本時出現問題。 它看起來像這樣:將XSLT轉換爲xml,按鍵分組

<library> 
    <authors> 
     <author id="1001">John</author> 
     <author id="1002">Tom</author> 
    </authors> 
    <articles> 
     <article> 
      <authorId>1001</authorId> 
      <title>Article1</title> 
     </article> 
     <article> 
      <authorId>1002</authorId> 
      <title>Article2</title> 
     </article> 
     <article> 
      <authorId>1001</authorId> 
      <title>Article3</title> 
     </article> 
    </articles> 
</library> 

我想它變換分析到:

<raport> 
    <authorArticles> 
     <author>John</author> 
     <articles> 
      <article>Article1</article> 
      <article>Article3</article> 
     </articles> 
    </authorArticles> 
    <authorArticles> 
     <author>Tom</author> 
     <articles> 
      <article>Article2</article> 
     </articles> 
    </authorArticles> 
</raport> 

我有主意,用每一個,對在作者id和neasted的文章,但我不知道怎麼樣去做吧。任何人都知道如何進行這種轉變?

+0

好問題,+1。演示使用密鑰的完整高效解決方案,請參閱我的答案。 :) – 2010-12-14 21:45:19

回答

1

這XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes"/> 

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

<xsl:template match="library"> 
    <raport> 
     <xsl:apply-templates select="authors/author"/> 
    </raport> 
</xsl:template> 

<xsl:template match="author"> 
    <authorArticles> 
     <xsl:call-template name="identity"/> 
     <articles> 
      <xsl:apply-templates select="../../articles/article[authorId = current()/@id]"/> 
     </articles> 
    </authorArticles> 
</xsl:template> 

<xsl:template match="article"> 
    <xsl:call-template name="identity"/> <!-- In case of more characteristics --> 
</xsl:template> 

<xsl:template match="title"> 
    <xsl:value-of select="."/> 
</xsl:template> 

<xsl:template match="author/@id | authorId"/> 

</xsl:stylesheet> 

有了這個XML輸入:

<library> 
<authors> 
    <author id="1001">John</author> 
    <author id="1002">Tom</author> 
</authors> 
<articles> 
    <article> 
     <authorId>1001</authorId> 
     <title>Article1</title> 
    </article> 
    <article> 
     <authorId>1002</authorId> 
     <title>Article2</title> 
    </article> 
    <article> 
     <authorId>1001</authorId> 
     <title>Article3</title> 
    </article> 
</articles> 
</library> 

提供這種需要的結果:

<raport> 
    <authorArticles> 
     <author>John</author> 
     <articles> 
      <article>Article1</article> 
      <article>Article3</article> 
     </articles> 
    </authorArticles> 
    <authorArticles> 
     <author>Tom</author> 
     <articles> 
      <article>Article2</article> 
     </articles> 
    </authorArticles> 
</raport> 

進一步優化可能是使用鑰匙,但它看起來過早與你的結構。

+0

大thx得到了這:) – niceNick44 2010-12-14 21:03:59

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="kArticleById" match="article" 
    use="authorId"/> 

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

<xsl:template match="/*"> 
    <raport> 
     <xsl:apply-templates select="authors/author"/> 
    </raport> 
</xsl:template> 

<xsl:template match="author"> 
    <authorArticles> 
    <xsl:call-template name="identity"/> 
    <articles> 
     <xsl:apply-templates select="key('kArticleById',@id)"/> 
    </articles> 
    </authorArticles> 
</xsl:template> 

<xsl:template match="title"> 
    <xsl:apply-templates/> 
</xsl:template> 
<xsl:template match="author/@id|articles|authorId"/> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<library> 
    <authors> 
     <author id="1001">John</author> 
     <author id="1002">Tom</author> 
    </authors> 
    <articles> 
     <article> 
      <authorId>1001</authorId> 
      <title>Article1</title> 
     </article> 
     <article> 
      <authorId>1002</authorId> 
      <title>Article2</title> 
     </article> 
     <article> 
      <authorId>1001</authorId> 
      <title>Article3</title> 
     </article> 
    </articles> 
</library> 

產生想要的,正確的結果

<raport> 
    <authorArticles> 
     <author>John</author> 
     <articles> 
     <article>Article1</article> 
     <article>Article3</article> 
     </articles> 
    </authorArticles> 
    <authorArticles> 
     <author>Tom</author> 
     <articles> 
     <article>Article2</article> 
     </articles> 
    </authorArticles> 
</raport> 

注意

  1. 使用/身份規則的壓倒一切的。

  2. 所有具有相同authorId的文章均使用鍵進行選擇。對於許多文章衆多的作者來說,這樣做效率更高。