Выбор элемента XSLT на основе выбора не работает

#xslt

Вопрос:

У меня есть следующий XML:

 lt;Documentgt;  lt;Rowgt;  lt;KEYgt;NIKE|JB|APPAREL|MENSlt;/KEYgt;  lt;Periodgt;Nov-21lt;/Periodgt;  lt;/Rowgt;  lt;Rowgt;  lt;KEYgt;FASCINATE|JB|ACCESSORIES|LADIESlt;/KEYgt;  lt;Matchesgt;  lt;Rowgt;  lt;KEYgt;FASCINATE|JB|ACCESSORIES|LADIESlt;/KEYgt;  lt;Periodgt;Nov-22lt;/Periodgt;  lt;/Rowgt;  lt;/Matchesgt;  lt;/Rowgt; lt;/Documentgt;  

Я хочу использовать XSLT для возврата вложенного /Matches/Row/Period , когда Document/Row/Period значение не определено (как во втором Row XML).

Итак, у меня есть следующий XSLT:

 lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://exampleincludednamespace.com/" exclude-result-prefixes="ns"gt; lt;xsl:output method="xml" omit-xml-declaration="yes" /gt; lt;xsl:template match="/"gt;  lt;Documentgt;  lt;xsl:for-each select="/Document/Row"gt;  lt;xsl:variable name="period" select="/Period" /gt;  lt;xsl:choosegt;  lt;xsl:when test="$period = null"gt;  lt;xsl:copygt;  lt;xsl:copy-of select="KEY | /Matches/Row/Period" /gt;  lt;/xsl:copygt;  lt;/xsl:whengt;  lt;xsl:otherwisegt;  lt;xsl:copygt;  lt;xsl:copy-of select="KEY | Period" /gt;  lt;/xsl:copygt;  lt;/xsl:otherwisegt;  lt;/xsl:choosegt;  lt;/xsl:for-eachgt;  lt;/Documentgt; lt;/xsl:templategt;  

lt;/xsl:таблица стилейgt;

Но он возвращает следующий вывод:

 lt;Documentgt;  lt;Rowgt;  lt;KEYgt;NIKE|JB|APPAREL|MENSlt;/KEYgt;  lt;Periodgt;Nov-21lt;/Periodgt;  lt;/Rowgt;  lt;Rowgt;  lt;KEYgt;FASCINATE|JB|ACCESSORIES|LADIESlt;/KEYgt;  lt;/Rowgt; lt;/Documentgt;  

(Обратите внимание, что он не возвращает вложенное /Matches/Row/Period во втором /Row .

Я ожидаю получить следующий результат:

 lt;Documentgt;  lt;Rowgt;  lt;KEYgt;NIKE|JB|APPAREL|MENSlt;/KEYgt;  lt;Periodgt;Nov-21lt;/Periodgt;  lt;/Rowgt;  lt;Rowgt;  lt;KEYgt;FASCINATE|JB|ACCESSORIES|LADIESlt;/KEYgt;  lt;Periodgt;Nov-22lt;/Periodgt;  lt;/Rowgt; lt;/Documentgt;  

Что я делаю не так?

Комментарии:

1. lt;xsl:variable name="period" select="/Period" /gt; никогда ничего не будет выбрано, если Period это не корневой элемент XML. Каков ожидаемый результат? Пожалуйста, добавьте это в свой вопрос.

2. добавлен ожидаемый результат

Ответ №1:

неопределенные или нулевые значения не проверяются при использовании XSLT/XPath expression = null , вы бы предпочли использовать (для наборов узлов) lt;xsl:when test="expression"gt; , например lt;xsl:when test="Period"gt; , чтобы для контекстного узла был хотя бы один Period дочерний элемент или test="not(Period)" чтобы проверить Period , что дочернего элемента нет.

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

Ответ №2:

Получилось работать с этим XSLT:

 lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://exampleincludednamespace.com/" exclude-result-prefixes="ns"gt; lt;xsl:output method="xml" omit-xml-declaration="yes" /gt; lt;xsl:template match="/"gt;  lt;Documentgt;  lt;xsl:for-each select="/Document/Row"gt;  lt;xsl:choosegt;  lt;xsl:when test="not(Period)"gt;  lt;xsl:copygt;  lt;xsl:copy-of select="KEY | Matches/Row/Period" /gt;  lt;/xsl:copygt;  lt;/xsl:whengt;  lt;xsl:otherwisegt;  lt;xsl:copygt;  lt;xsl:copy-of select="KEY | Period" /gt;  lt;/xsl:copygt;  lt;/xsl:otherwisegt;  lt;/xsl:choosegt;  lt;/xsl:for-eachgt;  lt;/Documentgt; lt;/xsl:templategt;  

lt;/xsl:таблица стилейgt;

Спасибо руководству @MartinHonnen.

Ответ №3:

Я верю, что это может быть просто:

XSLT 1.0

 lt;xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"gt; lt;xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/gt;  lt;xsl:template match="/Document"gt;  lt;xsl:copygt;  lt;xsl:for-each select="Row"gt;  lt;xsl:copygt;  lt;xsl:copy-of select="KEY | descendant::Period[1]" /gt;  lt;/xsl:copygt;  lt;/xsl:for-eachgt;  lt;/xsl:copygt; lt;/xsl:templategt;  lt;/xsl:stylesheetgt;