Как удалить <b /> из документа - PullRequest
1 голос
/ 18 ноября 2008

Я пытаюсь создать XSLT, который копирует большинство тегов, но удаляет пустые теги "<b/>". То есть он должен скопировать как есть "<b> </b>" или "<b>toto</b>", но полностью удалить "<b/>".

Я думаю, что шаблон будет выглядеть так:

<xsl:template match="b">
  <xsl:if test=".hasChildren()">
    <xsl:element name="b">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:if>
</xsl:template>

Но, конечно же, часть "hasChildren()" не существует ... Есть идеи?

Ответы [ 7 ]

3 голосов
/ 18 ноября 2008

dsteinweg поставил меня на правильный путь ... Я закончил делать:

<xsl:template match="b">
    <xsl:if test="./* or ./text()">
        <xsl:element name="b">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:if>
</xsl:template>
3 голосов
/ 18 ноября 2008

Это преобразование игнорирует любые элементы , которые не имеют дочерних узлов. Узел в этом контексте означает узел инструкции элемента, текста, комментария или обработки.

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="b[not(node()]"/>
</xsl:stylesheet>

Обратите внимание, что здесь мы используем один из самых фундаментальных шаблонов проектирования XSLT - используя преобразование идентичности и переопределяем его для определенных узлов.

Переопределяющий шаблон будет выбран только для узлов, которые являются элементами с именем "b" и не имеют (любые узлы как) дочерние элементы. Этот шаблон пуст (не имеет содержимого), поэтому его применение заключается в том, что соответствующий узел игнорируется / отбрасывается и не воспроизводится в выходных данных.

Эта техника очень мощная и широко используется для таких задач, а также для переименования, изменения содержимого или атрибутов, добавления дочерних или родных элементов к любому конкретному узлу, который может быть сопоставлен (каждый тип узла, за исключением узла пространства имен может использоваться в качестве шаблона соответствия в атрибуте «match»

Надеюсь, это помогло.

Приветствия

Димитр Новатчев

2 голосов
/ 18 ноября 2008

Интересно, будет ли это работать?

<xsl:template match="b">
  <xsl:if test="b/text()">
    ...
1 голос
/ 18 ноября 2008

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

<xsl:template match="b[not(node())] />

Это предполагает, что у вас есть шаблон идентификации позже в преобразовании, что звучит так же, как и у вас. Это автоматически скопирует любые теги «b» с содержимым, что вам нужно:

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

Редактировать: Теперь использует node (), как Dimitri, ниже.

1 голос
/ 18 ноября 2008

В качестве альтернативы можно сделать следующее:

<xsl:template match="b[not(text())]" />

<xsl:template match="b">
  <b>
    <xsl:apply-templates/>
  </b>
</xsl:template>
1 голос
/ 18 ноября 2008

Посмотрите, будет ли это работать.

<xsl:template match="b">
  <xsl:if test=".!=''">
    <xsl:element name="b">
     <xsl:apply-templates/>
    </xsl:element>
  </xsl:if>
</xsl:template>
0 голосов
/ 18 ноября 2008

Если у вас есть доступ для обновления исходного XML, вы можете попробовать использовать xml: space = preserve в корневом элементе

<html xml:space="preserve">
...
</html>

Таким образом, пространство в пустом теге сохраняется, и поэтому его можно отличить от в XSLT.

<xsl:template match="b">
   <xsl:if test="text() != ''">
   ....
   </xsl:if>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...