Преобразование многоэлементного XML в CSV с XSLT - PullRequest
0 голосов
/ 20 мая 2018

Я пытаюсь понять, как XSLT может выполнять итерации по нескольким элементам и выводить данные из этих элементов и их старших и младших братьев и сестер.См. Пример ниже:

<a>
    <b name="first">
        <c value="C Value">C Text</c>
        <d>D1 Text</d>
        <d>D2 Text</d>
        <e>E Text</e>
    </b>
    <b name="second">
        <c value="C Value">C Text</c>
        <d>D1 Text</d>
        <d>D2 Text</d>
        <d>D3 Text</d>
        <e>E Text</e>
    </b>
    <b name="third">
        <c value="C Value">C Text</c>
        <e>E Text</e>
    </b>
</a>

Я бы хотел, чтобы вывод был похож на следующий (для простоты предполагается, что текст каждого элемента не будет содержать запятых).

first,C Value,C Text,D1 Text,E Text
first,C Value,C Text,D2 Text,E Text
second,C Value,C Text,D1 Text,E Text
second,C Value,C Text,D2 Text,E Text
second,C Value,C Text,D3 Text,E Text
third,C Value,C Text,,E Text

Так что может бытьбыть произвольным числом <d> элементов (или ни одного вообще).Каждая строка CSV должна содержать информацию от <c> (старший брат <d>), информацию от одного экземпляра <d> и информацию от <e>, младший брат <d>.(Я могу придумать это понятие о младшем и старшем, но, кажется, это имеет смысл.)

Я раньше не работал с XSLT, поэтому я действительно не знаю, с чего начать.Примеры, которые я нашел для итерации по элементам, не проясняют, как я могу получить значения позже в документе (например, <e> в примере) и вернуться к другому экземпляру элемента (например, <d>).Я написал реализацию этого в Python с lxml, но хотел бы посмотреть, лучше ли подходит XSLT для этого преобразования.

РЕДАКТИРОВАТЬ: Я только что увидел, что был опубликован ответ, которыйЯ буду изучать подробно, чтобы попытаться понять это.Но просто чтобы поделиться тем, над чем я работал, вот XSL, который я разрабатывал.Он не может ничего выводить, когда нет значения <d>.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="text" encoding="iso-8859-1" />
    <xsl:strip-space elements="*" />

    <xsl:template match="a">       
        <xsl:for-each select="b">
            <xsl:call-template name="match-b"/>
        </xsl:for-each>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

    <xsl:template name="match-b" match="b">
        <xsl:for-each select="d">
            <xsl:value-of select="../@name"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="../c/@value"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="../c"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="../e"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Выход :

first,C value,C Text,D1 Text,E Text
first,C value,C Text,D2 Text,E Text
second,C value,C Text,D1 Text,E Text
second,C value,C Text,D2 Text,E Text
second,C value,C Text,D3 Text,E Text

1 Ответ

0 голосов
/ 20 мая 2018

Вы можете перейти к предыдущему или следующему брату или родительскому узлу, используя XPath.Чтобы вывести строку с XSLT 2 или более поздней версией, вы можете использовать xsl:value-of select="expression-to-compute-column-values" separator=",", как в

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">

  <xsl:output method="text"/>

  <xsl:mode name="add-dummy-d" on-no-match="shallow-copy"/>

  <xsl:variable name="normalized-input">
      <xsl:apply-templates mode="add-dummy-d"/>
  </xsl:variable>

  <xsl:template match="b[not(d)]/c" mode="add-dummy-d">
      <xsl:next-match/>
      <d/>
  </xsl:template>

  <xsl:template match="/">
      <xsl:apply-templates select="$normalized-input/a/b/d"/>
  </xsl:template>

  <xsl:template match="d">
      <xsl:value-of select="../@name, preceding-sibling::c/(@value, .), ., following-sibling::e" separator=","/>
      <xsl:text>&#10;</xsl:text>
  </xsl:template>

</xsl:stylesheet>

. Как сказано в комментарии, промежуточный шаг, добавляющий пустую d для тех b, которые неНеобходим или хотя бы один способ обеспечить получение последней строки выходного образца.

Онлайн-образец по адресу https://xsltfiddle.liberty -development.net / eiZQaF7 .

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