XSLT transformation to xml, grouping by key

前端 未结 2 496
北海茫月
北海茫月 2021-01-21 11:54

I have problem with write xsl to transform my xml to raport version. It looks like that:


    
        Jo         


        
相关标签:
2条回答
  • 2021-01-21 12:20

    This transformation:

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

    produces the wanted, 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:

    1. Use/overriding of the identity rule.

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

    0 讨论(0)
  • 2021-01-21 12:23

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

    The further optimization might be using keys, but it looks premature with your structure.

    0 讨论(0)
提交回复
热议问题