XSL рекурсивно игнорирует пустых детей - PullRequest
2 голосов
/ 15 декабря 2009

Попытка чего-то дурацкого в очистке многословного XML, которая заключается в рекурсивном удалении всех пустых узлов.

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

<foo>
  <bar>
    <baz/>
  </bar>
  <quux>  </quux>
</foo>

Я пытался использовать <xsl:if test="child::node()"> в своих шаблонах, но это не помогло. Вполне возможно, что ответ «иди по дереву, глупый», но похоже, что XSL должен уметь это делать?

Я бы ожидал

<foo>
  <bar>
    <baz/>
  </bar>
  <quux>  </quux>
  <quuux>Actual content</quuux>
</foo>

чтобы вернуться как

<foo>
  <quuux>Actual content</quuux>
</foo>

с этим фильтром я имею в виду.

Ответы [ 2 ]

5 голосов
/ 15 декабря 2009

Причина, по которой child::node() не сработала для вас, заключалась в том, что у вас есть дочерние узлы - это пробельные текстовые узлы. Вместо этого попробуйте что-то вроде normalize-space() != ''. Вам, вероятно, тоже не нужен if - введите вместо него match:

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

<xsl:template match="*[normalize-space() = '']"/>
4 голосов
/ 16 декабря 2009

Павел отвечает правильно. Две небольшие ошибки: вам нужно закрыть узел xsl:copy, а apply:templates использует select вместо match. Это будет окончательная версия:

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

<xsl:template match="*[normalize-space() = '']"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...