Вложите все вложенные элементы XML в новый элемент с помощью XSLT - PullRequest
0 голосов
/ 09 октября 2018

У меня есть XML-файл, который нуждается в некоторых исправлениях в своей структуре.Из-за размера указанного документа это должно быть сделано автоматически.
Базовая структура выглядит следующим образом:

<body>
    <div author='author1'>
        <lb n='1'/>Text1
        <lb n='2'/>Text2
    </div>
    <lb n='3'/>Text3
    <lb n='4'/>Text4
    <div author='author1'>
        <lb n='5'/>Text5
    </div>
    <add>xyz</add>
    <lb n='6'/>Text6
    <lb n='7'/>Text7
    <lb n='8'/>Text8
</body>

Я хочу поместить все, что еще не в div помечает div метки и помечает его атрибутом @author='author2'.Текст и структура перемещенных фрагментов должны оставаться такими, как есть, просто вложенными в div.Порядок также должен быть сохранен.
Полученный XML должен выглядеть примерно так:

<body>
    <div author='author1'>
        <lb n='1'/>Text1
        <lb n='2'/>Text2
    </div>
    <div author='author2'>
        <lb n='3'/>Text3
        <lb n='4'/>Text4
    </div>
    <div author='author1'>
        <lb n='5'/>Text5
    </div>
    <div author='author2'>
        <add>xyz</add>
        <lb n='6'/>Text6
        <lb n='7'/>Text7
        <lb n='8'/>Text8
    </div>
</body>

Мой текущий XSLT (который я написал до того, как заметил, что в XML больше элементов, чем просто lb) действительно ставит lb в правильное div, но перемещает все в конец и удаляет текст.
XSLT выглядит следующим образом:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="2.0">

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

<xsl:template match="body">
        <xsl:copy>
            <xsl:apply-templates select="*[not(self::lb)]"/>
            <div>
                <xsl:attribute name="resp">author2</xsl:attribute>
                <xsl:apply-templates select="lb"/>
            </div>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

И возвращает этот XML:

<?xml version="1.0"?>
<body><div author="author1">
        <lb n="1"/>Text1
        <lb n="2"/>Text2
    </div><div author="author1">
        <lb n="5"/>Text5
    </div><add>xyz</add><div resp="author2"><lb n="3"/><lb n="4"/><lb n="6"/><lb n="7"/><lb n="8"/></div></body>

Что я делаю не так?
Заранее спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

В качестве альтернативы использованию group-adjacent, вы можете использовать group-starting-with на xsl:for-each-group

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

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

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

  <xsl:template match="body">
    <xsl:copy>
      <xsl:for-each-group select="node()" group-starting-with="div">
        <xsl:apply-templates select="." />
        <xsl:if test="current-group()[2]">
          <div resp="author2">
            <xsl:apply-templates select="current-group()[position() gt 1]"/>
          </div>
        </xsl:if>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
0 голосов
/ 09 октября 2018

Попробуйте сгруппировать в XSLT 2.0

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

    <xsl:template match="body">
        <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="self::lb or self::add">
            <xsl:choose>
                <xsl:when test="current-grouping-key()">
                    <div author='author2'>
                        <xsl:apply-templates select="current-group()"/>
                    </div>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates  select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

См. Преобразование в https://xsltfiddle.liberty -development.net / bFDb2CW

...