XSLT - Как разделить детей родителей - PullRequest
2 голосов
/ 25 ноября 2010

Моя структура xml содержит программу в качестве родителя сертификатов и курсов. Я хочу разделить структуру, чтобы создать независимый список сертификатов и курсов без общего родителя программы. Исходная структура:

<root>
  <program>
    <program-name>Math</program-name>
    <certificate>...</certificate> <!-- There can 0 or more of these -->
    <course>...</course> <!-- There can 0 or more of these -->
  </program>
  <program>
    ...
  </program>
</root>

Вывод должен выглядеть так:

<root>
   <program-courses>
     <program>
       <program-name>Math</program-name>
       <course/> <!-- There can 0 or more of these -->
     </program>
     ...
   </program-courses>
   <program-certificates>
     <program>
       <program-name>Math</program-name>
       <certificate/> <!-- There can 0 or more of these -->
     </program>
     ...
   </program-certificates>
</root>

Обновление : Ответ с предложением Пола об использовании режима. Вот что стало для соответствующей части xslt:

<xsl:template match="root">
        <xsl:element name="root">
            <xsl:element name="program-courses">
                <xsl:apply-templates select="root/program-area" mode="course"/>
            </xsl:element>
            <xsl:element name="program-certificates">
                <xsl:apply-templates select="root/program-area" mode="certificate"/>
            </xsl:element>
        </xsl:element>           
    </xsl:template>

    <xsl:template match="program-area" mode="course">
        <xsl:element name="program-area">
           <!-- Get the name here -->
            <xsl:element name="course">
                <xsl:apply-templates select="course"/>
            </xsl:element>
        </xsl:element>
    </xsl:template>

    <xsl:template match="program-area" mode="certificate">
        <xsl:element name="program-area">
           <!-- Get the name here -->
            <xsl:element name="course">
                <xsl:apply-templates select="certificate"/>
            </xsl:element>
        </xsl:element>
    </xsl:template>

Обратите внимание, что это решение урезано по сравнению с реальным, поэтому оно может не работать как с исходным вводом.

Ответы [ 2 ]

1 голос
/ 25 ноября 2010

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="program">
        <xsl:apply-templates select="course[1]|certificate[1]"/>
    </xsl:template>
    <xsl:template match="course[1]">
        <program-courses>
            <program>
                <xsl:apply-templates select="../*[not(self::certificate)]"
                                     mode="copy"/>
            </program>
        </program-courses>
    </xsl:template>
    <xsl:template match="certificate[1]">
        <program-certificates>
            <program>
                <xsl:apply-templates select="../*[not(self::course)]"
                                     mode="copy"/>
            </program>
        </program-certificates>
    </xsl:template>
    <xsl:template match="node()" mode="copy">
        <xsl:call-template name="identity"/>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<root>
    <program-certificates>
        <program>
            <program-name>Math</program-name>
            <certificate>...</certificate>
        </program>
    </program-certificates>
    <program-courses>
        <program>
            <program-name>Math</program-name>
            <course>...</course>
        </program>
    </program-courses>
</root>

РЕДАКТИРОВАТЬ : Если вы хотите что-то более "push-стиля", как ваше опубликованное решение:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="node()" mode="certificate">
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="node()" mode="course">
        <xsl:call-template name="identity"/>
    </xsl:template>
    <xsl:template match="program">
        <program-courses>
            <program>
                <xsl:apply-templates mode="course"/>
            </program>
        </program-courses>
        <program-certificates>
            <program>
                <xsl:apply-templates mode="certificate"/>
            </program>
        </program-certificates>
    </xsl:template>
    <xsl:template match="course" mode="certificate"/>
    <xsl:template match="certificate" mode="course"/>
</xsl:stylesheet>
1 голос
/ 25 ноября 2010
  1. При выборе программы elements, вы можете использовать @mode (на apply-templates и соответствующий template), чтобы различать, работаете ли вы в пределах выхода program-courses или program-certificates

  2. Из root вы можете выбрать program/course или program/certificate для генерации вывода program.

  3. Начиная с root, вы можете использовать for-each select="program", а для части, предназначенной для вывода program-courses, извлечь только program-name и course element и выполнить соответствующее извлечение в части, которая выводит program-certificates.

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