2010-12-14 2 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> 

Я хочу tranform его:

<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> 

У меня есть идея использовать для каждого из них на протяжении идентификаторов в авторах и neasted статей, но я не знаю, как сделать это. Кто-нибудь знает, как сделать это преобразование?

+0

Хороший вопрос, +1. См. Мой ответ для полного и эффективного решения, демонстрирующего использование ключей. :) –

ответ

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

big thx получил это :) – niceNick44

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. Все статьи с таким же автором вводятся с помощью клавиш. Это значительно более эффективно в случае многих авторов со многими статьями.

Смежные вопросы