Преобразование идентичности XSLT с дополнительным копированием строки заголовка и манипулированием - PullRequest
0 голосов
/ 26 апреля 2018

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

Я хочу взять входной XML-документ и вывести аналогичную копию со следующими изменениями:

  1. Новая запись заголовка в том же формате, что и записи одного уровня.вставляется каждый раз, когда изменяется значение определенного элемента братьев и сестер.Элемент заголовка будет копией первого брата с некоторыми небольшими изменениями.
  2. Все обычные записи без заголовка также будут иметь некоторые измененные значения.

Я пытался использоватьhttp://exslt.org/common функция набора узлов, а также наборы узлов в качестве переменных в xslt 2.0, но потерянные.

Пример ввода, предполагается, что строки отсортированы по типу.

<fruits>
    <fruit>

        <row>1</row>
        <type> Apple </type>
        <name> Gala </name>
        <color> Red </color>
        <country> US </country>
    </fruit>

    <fruit>

        <row>2</row>
        <type> Apple </type>
        <name> Fuji </name>
        <color> Red </color>
        <country> US </country>
    </fruit>

    <fruit>

        <row>3</row>
        <type> Apple </type>
        <name> Golden Delcious </name>
        <color> Yellow </color>
        <country> US </country>
    </fruit>
    <fruit>

        <row>4</row>
        <type> Orange </type>
        <name> Clementine </name>
        <color> Orange </color>
        <country> US </country>
    </fruit>
    <fruit>
        <row>5</row>
        <type> Orange </type>
        <name> Sunburst </name>
        <color> Orange </color>
        <country> US </country>
    </fruit>
</fruits>

Это пример вывода.Для каждого набора строк по типу добавьте строку заголовка над строкой этого типа в том же формате.Имя и цвет должны быть обнулены в строке заголовка, а к значению строки должен быть добавлен символ 'H', в противном случае он совпадает со следующей обычной строкой.В следующих регулярных строках того же типа страна должна быть исключена.

<fruits>
    <fruit>

        <row>H1</row>
        <type> Apple </type>
        <name> </name>
        <color> </color>
        <country> US </country>
    </fruit>
    <fruit>

        <row>1</row>
        <type> Apple </type>
        <name> Gala </name>
        <color> Red </color>
        <country> </country>
    </fruit>

    <fruit>

        <row>2</row>
        <type> Apple </type>
        <name> Fuji </name>
        <color> Red </color>
        <country> </country>
    </fruit>

    <fruit>

        <row>3</row>
        <type> Apple </type>
        <name> Golden Delcious </name>
        <color> Yellow </color>
        <country> </country>
    </fruit>
    <fruit>

        <row>H4</row>
        <type> Orange </type>
        <name> </name>
        <color> </color>
        <country> US </country>
    </fruit>
    <fruit>

        <row>4</row>
        <type> Orange </type>
        <name> Clementine </name>
        <color> Orange </color>
        <country> </country>
    </fruit>
    <fruit>
        <row>5</row>
        <type> Orange </type>
        <name> Sunburst </name>
        <color> Orange </color>
        <country> </country>
    </fruit>
</fruits>

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- create the extra header row every time the type changes -->
    <xsl:template match="fruit">
        <xsl:choose>
            <xsl:when test="type != preceding-sibling::*[1]/type">
                <xsl:copy>
                    <xsl:apply-templates select="node() | @*"/>
                </xsl:copy>
            </xsl:when>
            <!-- create the header row for the first row where preceding sibling is null -->
            <xsl:when test="row = 1">
                <xsl:copy>
                    <xsl:apply-templates select="node() | @*"/>
                </xsl:copy>
            </xsl:when>
            <xsl:otherwise>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>



</xsl:stylesheet>

Решения в xslt 1.0 предпочтительнее, но 2.0 тоже подойдет.

СпасибоВы так много!

Ответы [ 4 ]

0 голосов
/ 26 апреля 2018

Вот еще один подход к решению вашего вопроса в XSLT версии 2.0:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="fruits">
        <fruits>
            <xsl:for-each-group select="fruit" group-by="type">
                <fruit>
                    <row>
                        <xsl:value-of select="concat('H', current-group()[1]//row)"></xsl:value-of>
                    </row>
                    <type> <xsl:value-of select="current-group()[1]//type"/></type>
                    <name> </name>
                    <color> </color>
                    <country> <xsl:value-of select="current-group()[1]//country"/> </country>
                </fruit>
                <xsl:copy-of select="current-group()"/>                
            </xsl:for-each-group>
       </fruits>
    </xsl:template>   
</xsl:stylesheet>
0 голосов
/ 26 апреля 2018

В XSLT 2.0 это

<xsl:template match="fruits">
  <fruits>
    <xsl:for-each-group select="fruit" group-adjacent="type">
      <xsl:copy>
        <row>H<xsl:value-of select="row"/></row>
        <type><xsl:value-of select="type"/></type>
        <name/>
        <color/>
        <country><xsl:value-of select="country"/></country>
      </xsl:copy>
      <xsl:copy-of select="current-group()"/>
    </xsl:for-each-group>
  </fruits>
</xsl:template>
0 голосов
/ 26 апреля 2018

Я отредактирую ответ соответственно -

Код сценария XSLT:

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="fruit">
        <xsl:variable name="type" select="child::type"/>
        <xsl:choose>
            <xsl:when test="preceding-sibling::*[1][type != $type] or (count(preceding-sibling::fruit) = 0)">
                <fruit>
                    <row>
                        <xsl:value-of select="concat('H', row)"/>
                    </row>
                    <type> <xsl:value-of select="type"/></type>
                    <name> </name>
                    <color> </color>
                    <country> <xsl:value-of select="country"/> </country>
                </fruit>
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Ниже вывод, сгенерированный XSLT-скриптом:

<?xml version="1.0" encoding="UTF-8"?>
<fruits>
    <fruit>
      <row>H1</row>
      <type> Apple </type>
      <name/>
      <color/>
      <country> US </country>
   </fruit>
   <fruit>

        <row>1</row>
        <type> Apple </type>
        <name> Gala </name>
        <color> Red </color>
        <country> US </country>
    </fruit>

    <fruit>

        <row>2</row>
        <type> Apple </type>
        <name> Fuji </name>
        <color> Red </color>
        <country> US </country>
    </fruit>

    <fruit>

        <row>3</row>
        <type> Apple </type>
        <name> Golden Delcious </name>
        <color> Yellow </color>
        <country> US </country>
    </fruit>
    <fruit>
      <row>H4</row>
      <type> Orange </type>
      <name/>
      <color/>
      <country> US </country>
   </fruit>
   <fruit>

        <row>4</row>
        <type> Orange </type>
        <name> Clementine </name>
        <color> Orange </color>
        <country> US </country>
    </fruit>
    <fruit>
        <row>5</row>
        <type> Orange </type>
        <name> Sunburst </name>
        <color> Orange </color>
        <country> US </country>
    </fruit>
</fruits>
0 голосов
/ 26 апреля 2018

Я отредактирую ответ соответствующим образом, но вы имеете в виду что-то подобное?

(Здесь я только преобразовываю узел "строки", например, ресурсы)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="row">
        <xsl:copy>H<xsl:value-of select="."/></xsl:copy>
    </xsl:template>

    <!-- create the extra header row every time the type changes -->
    <xsl:template match="fruit">
        <xsl:choose>
            <xsl:when test="type != preceding-sibling::*[1]/type">
                <xsl:copy>
                    <xsl:apply-templates select="node() | @*"/>
                </xsl:copy>
            </xsl:when>
            <!-- create the header row for the first row where preceding sibling is null -->
            <xsl:when test="row = 1">
                <xsl:copy>
                    <xsl:apply-templates select="node() | @*"/>
                </xsl:copy>
            </xsl:when>
            <xsl:otherwise>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

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