XSLT преобразование в xml, группировка по ключу - PullRequest
2 голосов
/ 14 декабря 2010

У меня проблема с записью xsl для преобразования моего xml в raport версию.Это выглядит так:

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

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

Ответы [ 2 ]

1 голос
/ 15 декабря 2010

Это преобразование :

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

1 голос
/ 15 декабря 2010

Это 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>

Дальнейшая оптимизация может быть с использованием ключей, но это выглядит преждевременно с вашей структурой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...