Проверьте, содержит ли набор узлов какое-либо значение в XSLT - PullRequest
7 голосов
/ 08 декабря 2008

Мне нужна помощь с синтаксисом XSLT. Вот мой сценарий, у меня есть XML-файл, который необходимо преобразовать в другой внешний вид XML-файла, у меня есть несколько разделов, в которых, если определенный набор узлов не содержит никакого значения, весь раздел не должен обрабатываться.

Вот пример XML:

<Dates>
    <Date>
        <VALUE1></VALUE1>
        <VALUE2></VALUE2>
        <VALUE3></VALUE3>
        <VALUE4></VALUE4>
        <VALUE5>3333</VALUE5>
    </Date>
    <Date>
        <VALUE1>AAAA</VALUE1>
        <VALUE2></VALUE2>
        <VALUE3>JJJJ</VALUE3>
        <VALUE4></VALUE4>
        <VALUE5>12345</VALUE5>
    </Date>
</Dates>

снимок экрана xml

Вот мой XSLT с оператором if, который не работает правильно

<xsl:for-each select="Level1/Level2/Level3">
    <xsl:if test="@VALUE1!=''">                    
    <MyDates>               
            <value_1>
                <xsl:value-of select="VALUE1"/> 
            </value_1>
            <value_2>
                <xsl:value-of select="VALUE2"/> 
            </value_2>
            <value_3>
                <xsl:value-of select="VALUE3"/> 
            </value_3>
            <value_4>
                <xsl:value-of select="VALUE4"/> 
            </value_4>       
    </MyDates>
    </xsl:if>   
</xsl:for-each>

Итак, как вы можете видеть, я в основном хочу, чтобы все узлы (VALUE1, VALUE2, VALUE3 и т. Д.) Имели значения или не обрабатывали и не переходили к следующему разделу

(Если вы не видите мысли XML, я также сделал снимок экрана)

Ответы [ 6 ]

12 голосов
/ 08 декабря 2008

Вы пытаетесь сопоставить элементы xml с именами "Level1", "Level2" и т. Д., Которые не существуют в документе. Затем вы ищете атрибут VALUE1 в последнем элементе.

Я думаю вы хотите что-то вроде этого:

<xsl:for-each select="Dates">
    <MyDates>
        <xsl:for-each select="Date">
        <xsl:if test="not(*[.=''])">
            <MyDate>
                <value_1>
                    <xsl:value-of select="VALUE1"/> 
                </value_1>
                <value_2>
                    <xsl:value-of select="VALUE2"/> 
                </value_2>
                <value_3>
                    <xsl:value-of select="VALUE3"/> 
                </value_3>
                <value_4>
                    <xsl:value-of select="VALUE4"/> 
                </value_4>               
            </MyDate>
        </xsl:if>
        </xsl:for-each>
    </MyDates>
</xsl:for-each>

Это добавит новый элемент MyDate, если каждое значение в соответствующем элементе Date не пусто.

Что он делает, это

  1. Создать новый элемент MyDates для каждого элемента Dates.
  2. Проверьте каждый элемент Date. * соответствует всем детям. [.=''] означает «пусто». Наконец, он оборачивает все это в нет. Это означает, что if только проходит, если нет ни одного дочернего элемента, который является пустым.
  3. Если у него нет пустых дочерних элементов, создается новый элемент MyDate с копией каждого значения.

Вы также можете ознакомиться с учебными пособиями по W3Schools XSL и XPath .

3 голосов
/ 09 декабря 2008

Вы не определили, что означает "значение узла".

Скорее всего, вы рассмотрите элемент, у которого есть текстовый дочерний элемент только для пробелов, который не имеет значения. В этом случае ниже приведено одно решение :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:template match="Date[not(*[not(normalize-space())])]">
       <xsl:copy-of select="."/>
     </xsl:template>

     <xsl:template match="text()"/>
</xsl:stylesheet>

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

Когда это преобразование применяется к следующему документу XML :

<Dates>
    <Date>
        <VALUE1></VALUE1>
        <VALUE2>  </VALUE2>
        <VALUE3></VALUE3>
        <VALUE4></VALUE4>
        <VALUE5>3333</VALUE5>
    </Date>
    <Date>
        <VALUE1>AAAA</VALUE1>
        <VALUE2>1</VALUE2>
        <VALUE3>JJJJ</VALUE3>
        <VALUE4>1</VALUE4>
        <VALUE5>12345</VALUE5>
    </Date>
</Dates> 

Получен правильный результат :

<Date>
    <VALUE1>AAAA</VALUE1>
    <VALUE2>1</VALUE2>
    <VALUE3>JJJJ</VALUE3>
    <VALUE4>1</VALUE4>
    <VALUE5>12345</VALUE5>
</Date>
2 голосов
/ 08 мая 2010

Я думаю, вы тоже можете это сделать. Вместо проверки узла. VALUE1 / text () проверит, есть ли внутри узла какой-либо текст. Возможно, вы захотите убедиться, что для них нет пробелов. Также вы можете увидеть, есть ли у элемента VALUE1 дочерний узел.

<xsl:if test="VALUE1/text()">                    

</xsl:if>   

<xsl:if test="VALUE1/child::node()">                    

</xsl:if>  
2 голосов
/ 24 февраля 2009
<xsl:for-each select="Level1/Level2/Level3">
<MyDates>
    <xsl:if test="VALUE1!=''">
        <value_1>
            <xsl:value-of select="VALUE1"/>
        </value_1>
    </xsl:if>
    <xsl:if test="VALUE2!=''">
        <value_2>
            <xsl:value-of select="VALUE2"/>
        </value_2>
    </xsl:if>
    <xsl:if test="VALUE3!=''">
        <value_3>
            <xsl:value-of select="VALUE3"/>
        </value_3>
    </xsl:if>
    <xsl:if test="VALUE4!=''">
        <value_4>
            <xsl:value-of select="VALUE4"/>
        </value_4>
    </xsl:if>
</MyDates>

2 голосов
/ 08 декабря 2008

@ является избыточным - это относится к атрибутам XML.

Вы пытаетесь проверить элемент, поэтому просто отбросьте @.

Дополнительно:

  • Level1 / Level2 / Level3 не так
  • Вы проверяете только VALUE1, но хотите проверить все значения (что можно сделать с помощью *)
0 голосов
/ 18 апреля 2013
<xsl:template match="Dates">
<table border="1">
<tr bgcolor="#9acd32"><th>NAME</th><th>INVALUE</th></tr>
 <xsl:for-each select="Date">
  <xsl:if test="(VALUE1 != '') and (VALUE2 != '') and (VALUE3 != '') and (VALUE4 != '') and (VALUE5 != '')" >
     <tr><td>VALUE1</td><td><xsl:value-of select="VALUE1"></xsl:value-of></td></tr>
     <tr><td>VALUE2</td><td><xsl:value-of select="VALUE2"></xsl:value-of></td></tr>
     <tr><td>VALUE3</td><td><xsl:value-of select="VALUE3"></xsl:value-of></td></tr>
     <tr><td>VALUE4</td><td><xsl:value-of select="VALUE4"></xsl:value-of></td></tr>
     <tr><td>VALUE5</td><td><xsl:value-of select="VALUE5"></xsl:value-of></td></tr>
 </xsl:if>
 </xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...