рефакторинг XML с помощью XSL - PullRequest
1 голос
/ 04 ноября 2010

Мне нужно переместить элементы <sectionid/> и <sponsor/> внутри соответствующих <amendment/>.

Вот пример:

От:

<root>
      <sectionid>A</sectionid>
      <sponsor>john</sponsor>
      <sponsor>paul</sponsor>
      <amendment>
            <id>1</id>
            <text>some text</text>
      </amendment>
      <sectionid>B</sectionid>
      <sponsor>peter</sponsor>
      <amendment>
            <id>5</id>
            <text>some text</text>
      </amendment>
      <amendment>
            <id>4</id>
            <text>some text</text>
      </amendment>
      <sponsor>max</sponsor>
      <amendment>
            <id>6</id>
            <text>some text</text>
      </amendment>
      <amendment>
            <id>7</id>
            <text>some text</text>
      </amendment>

</root>

до:

<root>
      <amendment>
            <sectionid>A</sectionid>
            <sponsor>john</sponsor>
            <sponsor>paul</paul>
            <id>1</id>
            <text>some text</text>
      </amendment>
      <amendment>
            <sectionid>B</sectionid>
            <sponsor>peter</sponsor>
            <id>5</id>
            <text>some text</text>
      </amendment>
      <amendment>
            <sectionid>B</sectionid>
            <sponsor>peter</sponsor>
            <id>4</id>
            <text>some text</text>
      </amendment>
      <amendment>
            <sectionid>B</sectionid>
            <sponsor>max</sponsor>
            <id>6</id>
            <text>some text</text>
      </amendment>
      <amendment>
            <sectionid>B</sectionid>
            <sponsor>max</sponsor>
            <id>7</id>
            <text>some text</text>
      </amendment>

</root>

Примечание 1: элемент <section/> применяется ко всем <amendments/> до следующего <sectionid/>

Примечание 2: элемент <sponsor/> применяется ко всем <amendments/> до следующего списка <sponsor/>.

Примечание 3: значения //amendment/id не являются последовательными.

Как это преобразование можно сделать с помощью XSLT 1.0.

Ответы [ 2 ]

1 голос
/ 04 ноября 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:template match="node()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="amendment">
  <xsl:copy>
     <xsl:apply-templates select="@*"/>

     <xsl:variable name="vSectionId" 
          select="preceding-sibling::sectionid[1]"/>
     <xsl:variable name="vprevAmendment" 
          select="preceding-sibling::amendment[1]"/>

     <xsl:apply-templates select="$vSectionId" mode="copy"/>

     <xsl:variable name="vsectSponsors"
      select="preceding-sibling::sponsor
               [generate-id(preceding-sibling::sectionid[1])
               =
                generate-id($vSectionId)
               ]"/>

     <xsl:variable name="vamdSponsors"
      select="preceding-sibling::sponsor
               [generate-id(preceding-sibling::amendment[1])
               =
                generate-id($vprevAmendment)
               ]"/>


     <xsl:apply-templates mode="copy"
          select="$vamdSponsors|$vsectSponsors[not($vamdSponsors)]"/>
    <xsl:apply-templates select="node()|@*"/>
   </xsl:copy>
 </xsl:template>

 <xsl:template match="*" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>

 <xsl:template match="sectionid|sponsor"/>
</xsl:stylesheet>

при применении к предоставленному XML-документу :

<root>
      <sectionid>A</sectionid>
      <sponsor>john</sponsor>
      <sponsor>paul</sponsor>
      <amendment>
            <id>1</id>
            <text>some text</text>
      </amendment>
      <sectionid>B</sectionid>
      <sponsor>peter</sponsor>
      <amendment>
            <id>5</id>
            <text>some text</text>
      </amendment>
      <amendment>
            <id>4</id>
            <text>some text</text>
      </amendment>
      <sponsor>max</sponsor>
      <amendment>
            <id>6</id>
            <text>some text</text>
      </amendment>
</root>

создает искомое, правильные результаты :

<root>
   <amendment>
      <sectionid>A</sectionid>
      <sponsor>john</sponsor>
      <sponsor>paul</sponsor>
      <id>1</id>
      <text>some text</text>
   </amendment>
   <amendment>
      <sectionid>B</sectionid>
      <sponsor>peter</sponsor>
      <id>5</id>
      <text>some text</text>
   </amendment>
   <amendment>
      <sectionid>B</sectionid>
      <sponsor>peter</sponsor>
      <id>4</id>
      <text>some text</text>
   </amendment>
   <amendment>
      <sectionid>B</sectionid>
      <sponsor>max</sponsor>
      <id>6</id>
      <text>some text</text>
   </amendment>
</root>
1 голос
/ 04 ноября 2010

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*">
        <xsl:param name="pSectionId"/>
        <xsl:param name="pSponsors"/>
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]">
            <xsl:with-param name="pSectionId" select="$pSectionId"/>
            <xsl:with-param name="pSponsors" select="$pSponsors"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="sectionid">
        <xsl:param name="pSectionId"/>
        <xsl:param name="pSponsors"/>
        <xsl:apply-templates select="following-sibling::node()[1]">
            <xsl:with-param name="pSectionId" select="."/>
            <xsl:with-param name="pSponsors" select="$pSponsors"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="sponsor">
        <xsl:param name="pSectionId"/>
        <xsl:param name="pSponsors"/>
        <xsl:apply-templates select="following-sibling::node()[1]">
            <xsl:with-param name="pSectionId" select="$pSectionId"/>
            <xsl:with-param name="pSponsors" select="."/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="sponsor[preceding-sibling::node()[1]/self::sponsor]">
        <xsl:param name="pSectionId"/>
        <xsl:param name="pSponsors"/>
        <xsl:apply-templates select="following-sibling::node()[1]">
            <xsl:with-param name="pSectionId" select="$pSectionId"/>
            <xsl:with-param name="pSponsors" select="$pSponsors|."/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="amendment">
        <xsl:param name="pSectionId"/>
        <xsl:param name="pSponsors"/>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:copy-of select="$pSectionId|$pSponsors"/>
            <xsl:apply-templates select="node()[1]"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]">
            <xsl:with-param name="pSectionId" select="$pSectionId"/>
            <xsl:with-param name="pSponsors" select="$pSponsors"/>
        </xsl:apply-templates>
    </xsl:template>
</xsl:stylesheet>

Выход:

<root>
    <amendment>
        <sectionid>A</sectionid>
        <sponsor>john</sponsor>
        <sponsor>paul</sponsor>
        <id>1</id>
        <text>some text</text>
    </amendment>
    <amendment>
        <sectionid>B</sectionid>
        <sponsor>peter</sponsor>
        <id>5</id>
        <text>some text</text>
    </amendment>
    <amendment>
        <sectionid>B</sectionid>
        <sponsor>peter</sponsor>
        <id>4</id>
        <text>some text</text>
    </amendment>
    <amendment>
        <sectionid>B</sectionid>
        <sponsor>max</sponsor>
        <id>6</id>
        <text>some text</text>
    </amendment>
    <amendment>
        <sectionid>B</sectionid>
        <sponsor>max</sponsor>
        <id>7</id>
        <text>some text</text>
    </amendment>
</root>

Примечание : Мелкозернистый обход. Линейная сложность.

Редактировать : Новый входной сэмпл.

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