2016-02-03 2 views
0

Я использую xslt для преобразования моего xml таким образом, что в теге отображаются только те элементы, которые отображаются в теге <AffectedItems>. <Changes>. Я новичок в xslt, поэтому, пожалуйста, расскажите, что я делаю неправильно здесь.
Вот XML:Не удается запустить оператор if в вложенном цикле в xslt

<Product> 
    <Items> 
     <Item itemIdentifier="1102607"> 
     </Item> 
     <Item itemIdentifier="1890456"> 
     </Item> 
    </Items> 
    <Changes> 
     <Change> 
     <AffectedItems> 
      <AffectedItem itemIdentifier="1102607"> 
      </AffectedItem> 
     </AffectedItems> 
     </Change> 
    </Changes> 
</Product> 

Вот соответствующая часть в XSLT в:

<xsl:for-each select="Product"> 
    <xsl:variable name="var3_current" select="."/> 
    <Items> 
    <xsl:for-each select="Items/Item"> 
     <xsl:for-each select="Changes/Change/AffectedItems/AffectedItem"> 
     <xsl:if test="floor(@itemIdentifier) = floor(Changes/Change/AffectedItems/AffectedItem/@itemIdentifier)"> 
      <Item> 
      <xsl:attribute name="itemIdentifier"> 
      <xsl:value-of select="floor(@itemIdentifier)"/> 
      </Item> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:for-each> 
    </Items> 
    <Changes> 
    <Change> 
     <AffectedItems> 
     <AffectedItem> 
     <xsl:attribute name="itemIdentifier"> 
      <xsl:value-of select="floor(Changes/Change/AffectedItems/AffectedItem/@itemIdentifier)"/> 
     </AffectedItem> 
     </AffectedItems> 
    </Change> 
    </Changes> 
</xsl:for-each> 

Он проходит через все пункты, но не ставит ни в выходной XML. Таким образом, полученный xml имеет пустой тег элементов

<Items/> 
+0

Можете ли вы показать свой ожидаемый результат в этом случае? Вы пытаетесь вывести элементы 'Item', чей' itemIdentifier' указан в 'AffectedItems'? Благодаря! –

+0

Да, это именно то, что я хочу. Мой ожидаемый результат был бы просто «item», где «itemIdentifier» соответствует. –

ответ

0

Основная проблема заключается в одном из контекстов. Вы начинаете с xsl:for-each на элементе Item, который позиционирует вас на этом элементе Item, но их вы делаете xsl:for-each на Changes. Это означает, что он ищет имена элементов Changes в качестве ребенка Item, но их нет. Таким образом, ваш вложенный xsl:for-each должен выглядеть следующим образом:

<xsl:for-each select="../../Changes/Change/AffectedItems/AffectedItem"> 

Однако, есть еще проблема с xsl:if в этом, как вы теперь расположены на AffectedItem, не Item вы были размещены на. Это означает, что ваш xsl:if проверяет itemIdentifier текущего AffectedItem против узла-потомка, начиная с Changes, которого нет.

Чтобы обойти эту проблему, ваш xsl:for-each должен выглядеть следующим образом

<xsl:for-each select="Items/Item"> 
    <xsl:variable name="Item" select="."/> 
    <xsl:for-each select="../../Changes/Change/AffectedItems/AffectedItem"> 
     <xsl:if test="floor(@itemIdentifier) = floor($Item/@itemIdentifier)"> 
      <Item> 
       <xsl:value-of select="floor(@itemIdentifier)"/> 
      </Item> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:for-each> 

Однако, это на самом деле не является идеальным подходом. Здесь вам могут пригодиться две вещи. Во-первых, это использование Identity Transform для копирования существующих элементов. Во-вторых, используется xsl:key для поиска AffectedItem элементов.

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

Попробуйте это гораздо более простой XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" /> 

    <xsl:key name="Affected" match="AffectedItem" use="number(@itemIdentifier)" /> 

    <xsl:template match="Item[not(key('Affected', number(@itemIdentifier)))]" /> 

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

Я удалил использование floor в данном примере, так как я не мог понять, почему вы пол целый ряд.

+0

Большое вам спасибо! Это очень помогло. Теперь он пересекает оба цикла, и он также проверяет оператор if, но он по-прежнему не выбирает соответствующие элементы. Я использую первый метод, потому что это только мой первый день с xslt, и я более комфортно с этим. И я заменил $ Item на ../../Items/Item, потому что в противном случае он сказал «необъявленная переменная Item», и я ничего не знаю о переменных здесь. –

+0

Посмотрите на http://xsltransform.net/3NJ38ZC, чтобы увидеть первый метод в действии.Тем не менее, стоит потратить время и силы на изучение шаблона идентификации, поскольку это фундаментальный шаблон проектирования в XSLT. Как вы можете видеть из моего ответа, это действительно уменьшает размер XSLT. –

+0

Но что вы сказали, копирует AffectedItems в Items, правильно? Но мне нужны все атрибуты Items (которые я здесь не показывал). AffectedItems не имеет одинаковых атрибутов. –

Смежные вопросы