Я не мастер XSLT.

У меня есть текущий XSLT, который я использую для удаления пустых узлов:

 string strippingStylesheet = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
                "<xsl:template match=\"@*|node()\">" +
                "<xsl:if test=\". != ''\">" +
                "<xsl:copy>" + 
                "<xsl:apply-templates select=\"@*|node()\"/>" +
                "</xsl:copy>" + 
                "</xsl:if></xsl:template></xsl:stylesheet>";

Мне нужно найти способ также удалить узлы с -1 в них. Предыдущий разработчик подумал, что было бы неплохо сделать для каждого int в системе значение по умолчанию -1, и да, это означает, что все поля БД имеют в них -1 вместо null.

Итак, как бы я ни хотел победить мертвую лошадь (палкой, битой, базукой), мне нужно вернуться к работе и сделать это.

Любая помощь была бы велика.

7
Ryan Ternier 10 Дек 2010 в 03:12
Хороший вопрос, +1. См. В моем ответе подходящее определение «пустого узла» и полное, но очень короткое решение. :)
 – 
Dimitre Novatchev
10 Дек 2010 в 05:41
2
Другое решение - просто изменить строку "<xsl:if test=\". != ''\">" на "<xsl:if test=\". != '' and . != -1\">".
 – 
LarsH
10 Дек 2010 в 10:05

2 ответа

Лучший ответ

У меня есть текущий XSLT, который я использую для удаления пустых узлов:

. . . . . . . . .

Мне нужно найти способ также удалить узлы с -1 в них

Я предполагаю, что требуется удалить все «пустые узлы».

Обработка зависит от определения «пустой узел». Одно разумное определение в вашем случае: Любой элемент, который не имеет атрибутов и дочерних элементов или не имеет атрибутов и имеет только один дочерний элемент, который является текстовым узлом со значением -1 .

Вот простое решение для этого определения.

Это преобразование .

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

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

 <xsl:template match="*[not(@*) and not(*) and (not(text()) or .=-1)]"/>
</xsl:stylesheet>

при применении к этому образцу XML-документа :

<t>
 <a>-1</a>
 <a>2</a>
 <b><c/></b>
 <d>-1</d>
 <d>15</d>
 <e x="1"/>
 <f>foo</f>
</t>

дает желаемый, правильный результат :

<t>
   <a>2</a>
   <b/>
   <d>15</d>
   <e x="1"/>
   <f>foo</f>
</t>
12
Dimitre Novatchev 10 Дек 2010 в 16:49
1
Думаю, может быть, вместо and not(text() or .=-1) вы имели в виду and (not(text()) or . = -1)) ... верно? Это объясняет, почему в вашем выводе отображаются узлы, содержащие только -1.
 – 
LarsH
10 Дек 2010 в 10:03
@LarsH: Спасибо, что заметили это. Я очень устал вчера вечером, когда писал ответ. Исправлено сейчас.
 – 
Dimitre Novatchev
10 Дек 2010 в 16:49

В простом случае это должно сработать:

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

<xsl:template match="*[. = '' or . = '-1']"/>

С помощью этого простого ввода:

<root>
    <node></node>
    <node>-1</node>
    <node>2</node>
    <node>8</node>
    <node>abc</node>
    <node>-1</node>
    <node></node>
    <node>99</node>
</root>

Результат будет:

<root>
    <node>2</node>
    <node>8</node>
    <node>abc</node>
    <node>99</node>
</root>
5
Flack 10 Дек 2010 в 03:20