2008-12-08 2 views
7

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

Вот пример 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> 

screenshot of xml

Вот мой XSLT с утверждением, что если не работать правильно

<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 задумался, я также сделал снимок экрана)

+0

Ваш XSLT не прошел. – 2008-12-08 19:55:39

+0

Возможно, если вы включите образец * output *? – Alastair 2008-12-08 20:17:02

ответ

12

Вы пытаетесь сопоставить элементы 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 элемент для каждого элемента даты.
  2. Проверьте каждый элемент даты. * соответствует всем детям. [.=''] означает «пусто». Наконец, он обертывает все это в нет. Это означает, что если только проходит, если нет никакого дочернего пустого.
  3. Если у него нет детей, которые пусты, он создает новый элемент MyDate с копией каждого значения.

Вы также можете проверить w3schools XSL и XPath учебники.

2

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

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

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

  • Level1/Level2/Level3 неправильно
  • Вы тестируете для VALUE1 только, но хочу проверить для всех значений (которые могут быть сделаны с *)
3

Вы не определили, что это значит, что «узел имеет значение».

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

 
<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> 

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

Когда это преобразование применяется на следующий документ 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
<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

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

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

</xsl:if> 

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

</xsl:if> 
0
<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> 
Смежные вопросы