В XSLT, как я могу вставить соответствующие теги, которые применяются к различным шаблонам - PullRequest
1 голос
/ 20 мая 2011

Я очень плохо знаком с XSLT и просто не смог найти решение моей проблемы. У меня есть XML-файл, который выглядит как (и я не могу изменить то, как этот XML выглядит, понимая, что это немного странно):

<account>
    <name>accountA</name>
</account>
<period>
    <type>priormonth</type>
</period>
<period>
    <type>currentmonth</type>
</period>
<account>
    <name>accountB</name>
</account>
<period>
    <type>priormonth</type>
</period>
<period>
    <type>currentmonth</type>
</period>

Файл xml может иметь переменную количество наборов данных счета / периода / периода, но они всегда находятся в таком порядке.

У меня есть файл xsl, который выглядит так:

<xsl:template match="/">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="account">
    <name> <xsl:value-of select="name"/> </name>
</xsl:template>

<xsl:template match="period">
    <type> <xsl:value-of select="type"/> </type>
</xsl:template>

Вышеописанное прекрасно работает, потому что имеет дело с несколькими вхождениями аккаунта / периода / периода, и мой вывод выглядит так:

<name>accountA</name>
<type>priormonth</type>
<type>currentmonth</type>
<name>accountB</name>
<type>priormonth</type>
<type>currentmonth</type>

Однако я хочу вставить некоторые дополнительные теги, чтобы вывод на самом деле выглядел так:

<account>
    <name>accountA</name>
    <period>
        <type>priormonth</type>
        <type>currentmonth</type>
    </period>
</account>
<account>
    <name>accountB</name>
    <period>
        <type>priormonth</type>
        <type>currentmonth</type>
    </period>
</account>

Есть ли способ сделать это? Извиняюсь, если моя терминология не совсем верна. Спасибо

Ответы [ 2 ]

2 голосов
/ 20 мая 2011

Попробуйте это:

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

  <xsl:template match="account">
    <xsl:copy>
      <xsl:apply-templates />
      <period>
        <xsl:apply-templates select="following-sibling::period[generate-id(preceding-sibling::account[1]) = generate-id(current())]/*" />
      </period>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="period" />

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

Оператор select немного запутан, но в основном он выбирает всех period братьев и сестер после каждого элемента account, где первый элемент account, предшествующий ему, является текущим.

1 голос
/ 20 мая 2011

В следующем XSLT предполагается, что источник xml в точности соответствует представленному в вашем вопросе (кроме отсутствующего корня, из-за которого исходный документ плохо сформирован).В этом случае вам не нужно преобразование личности.Более того, если вашему account нужны только первые два следующих period, вы можете использовать более простой XPath.


XSLT 1.0 протестировано в Saxon-HE 9.2.1.1J

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

    <xsl:template match="/root">
        <xsl:copy>
            <xsl:apply-templates select="account"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="account">
        <xsl:copy>
            <xsl:copy-of select="name" />
            <period>
                <xsl:copy-of select="following-sibling::period[position()&lt;=2]/type" />
            </period>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="period" />

</xsl:stylesheet>

Применяется к этому входу:

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
    <account>
        <name>accountA</name>
    </account>
    <period>
        <type>march</type>
    </period>
    <period>
        <type>currentmonth</type>
    </period>
    <account>
        <name>accountB</name>
    </account>
    <period>
        <type>priormonth</type>
    </period>
    <period>
        <type>currentmonth</type>
    </period>
</root>

Дает:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <account>
      <name>accountA</name>
      <period>
         <type>march</type>
         <type>currentmonth</type>
      </period>
   </account>
   <account>
      <name>accountB</name>
      <period>
         <type>priormonth</type>
         <type>currentmonth</type>
      </period>
   </account>
</root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...