XSLT разделить элементы по splitter-element - PullRequest
0 голосов
/ 11 мая 2018

Я пытался объединить решения с похожими вопросами, заданными здесь, но все они работают в очень специфических случаях. Мой случай следующий: у меня есть произвольный XML-документ, который содержит некоторые теги, скажем, <separator/>. Я хочу разделить родительские элементы этих тегов следующим образом:

ВХОД:

<some_tag some_attr="some_value">
    some text
    <some_other_tag>some another text</some_other_tag>
    <separator/>
    some other content
</some_tag>

ВЫВОД:

<some_tag some_attr="some_value">
    some text
    <some_other_tag>some another text</some_other_tag>
</some_tag>
<separator/>
<some_tag some_attr="some_value">
    some other content
</some_tag>

Кроме того, я ограничен XSLT 1.0, так как Xalan используется в проекте

1 Ответ

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

Либо используйте рекурсию брата, либо используйте ключ, чтобы найти узлы, «принадлежащие» разделителю. Требуется дополнительная осторожность для копирования содержимого после последнего разделителя:

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="sep" match="*[separator]/node()[not(self::separator)]" use="generate-id(following-sibling::separator[1])"/>

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

  <xsl:template match="*[separator]">
      <xsl:apply-templates select="separator" mode="split"/>
      <xsl:if test="separator[last()]/following-sibling::node()">
          <xsl:copy>
              <xsl:apply-templates select="@* | separator[last()]/following-sibling::node()"/>
          </xsl:copy>
      </xsl:if>
  </xsl:template>

  <xsl:template match="separator" mode="split">
      <xsl:apply-templates select=".." mode="split">
          <xsl:with-param name="separator" select="."/>
      </xsl:apply-templates>
      <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="*" mode="split">
      <xsl:param name="separator"/>
      <xsl:copy>
          <xsl:apply-templates select="@* | key('sep', generate-id($separator))"/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / pPqsHTc

Обратите внимание, что если вы используете Xalan Java, то в мире Java это намного проще с Saxon 9 и XSLT 2/3 <xsl:for-each-group select="node()" group-adjacent="boolean(self::separator)"> или group-starting-with="separator".

...