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

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

Использование того, что в этом вопросеЯ расширил его ...

<farm>
    <foo>
    <bar>
        <baz/>
    </bar>
    <quux>  </quux>
    <quuux>Actual content</quuux>
    </foo>
    <sounds>
        <moo>
            <meow>
                <buzz></buzz>
            </meow>
        </moo>
        <birds>
            <cluck>  </cluck>
            <quack></quack>
        </birds>
    </sounds>
</farm>

Как я могу просто исключить <sounds> и все его дочерние элементы (если они все пусты), оставляя пустые узлы, такие как foo, bar и baz.В требованиях к xml, который я создаю, должны присутствовать определенные теги, даже если они пустые, но некоторые должны быть удалены, если они пустые.

Чтобы пойти еще дальше, если у меня есть ...

<farm>
    <foo>
    <bar>
        <baz/>
    </bar>
    <quux>  </quux>
    <quuux>Actual content</quuux>
    </foo>
    <sounds>
        <moo>
            <meow>
                <buzz>"zzzz"</buzz>
            </meow>
        </moo>
        <birds>
            <cluck>  </cluck>
            <quack></quack>
        </birds>     <!-- Fixed by edit -->
    </sounds>
</farm>

В этом примере <sounds>, <moo>, <meow> и <buzz> должны остаться, поскольку <buzz> имеет значение, но <birds> и его дочерние элементы должны быть удалены.

Это кажется мне таким сложным, я не уверен, каким будет самый простой способ сделать это.

Большое спасибо за ваше руководство, так как у меня кружится голова от такого количества кругов!

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Если ваш процессор не поддерживает XSLT 3.0, вот вариант XSLT 1.0 ...

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

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

  <xsl:template match="*[ancestor-or-self::sounds][not(string())]"/>

</xsl:stylesheet>

Fiddle, например # 1: http://xsltfiddle.liberty -development.net / jyH9rNp

Fiddle, например № 2: http://xsltfiddle.liberty -development.net / jyH9rNp / 1

0 голосов
/ 21 ноября 2018

Предполагая XSLT 3 (поддерживается для платформы Java с Saxon 9.8 и 9.9 и для платформы .NET с Saxon 9.8, также Altova 2017/2018/2019), вы можете использовать xsl:where-populated вместе с xsl:next-match для sounds и любые элементы-потомки и преобразование идентичности для остальных;Кроме того, вам нужно убрать пробел, иначе <cluck> </cluck> не будет удалено:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:template match="sounds | sounds//*">
      <xsl:where-populated>
          <xsl:next-match/>
      </xsl:where-populated>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / gWmuiKn / 0 имеет ваш первый ввод и https://xsltfiddle.liberty -development.net / gWmuiKn / 1 ваш второй.

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