Convert XSLT to xml, key grouping

I have a problem writing xsl to convert my xml to raport version. It looks like this:

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

I want to convert it to:

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

I have an idea to use for each, for identifiers in authors and for articles, but I do not know how to do this. Does anyone know how to do this conversion?

+2
source share
2 answers

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

With this XML input:

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

Provides this necessary result:

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

Further optimization may involve the use of keys, but it looks premature with your structure.

+1
source

This conversion is :

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

when applied to the provided XML document :

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

creates the desired, correct result :

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

Notes

  • Use / override identification rule .

  • All articles with the same authorId are selected using the keys . This is significantly more effective in the case of many authors with many articles.

+1
source

All Articles