Выберите узлы с помощью key () на основе условия
У меня есть ситуация, когда мне нужно выбрать узлы, основанные на определенных условиях, а затем применить группировку Мюнха, чтобы получить уникальные значения. Я нахожусь на XSLT 1.0
<Parent>
<Child>
<A></A>
<B></B>
<C></C>
</Child>
<Child>
<A></A>
<B></B>
<C></C>
</Child>
<Child>
<A></A>
<B></B>
<C></C>
</Child>
</Parent>
Условие, которое я имею для атрибута use, является: Если не пусто, в противном случае использовать использовать А. Б.
Я придумал решение, которое будет работать для фиксированных значений ширины для узлов A и B. Поэтому, если A и B имеют длину n, я могу сделать что-то вроде этого:
<xsl:key name="groupKey" match="/Parent/Child" use="substring(concat(A,B),1,n)">
Итак, если A нет, я могу использовать B. Но у меня нет удалось выяснить, как использовать string-length() для получения выражения переменной длины для A и B. Есть идеи?
3 ответа:
Если вы хотите использовать функцию
concat()
:use="concat(A, B[not(string(../A)])"
И если под blank вы подразумеваете пустой или только пробел, то используйте:
use="concat(A, B[not(normalize-space(../A)])"
Наконец, если вы действительно хотите использовать и
concat()
, иsubstring()
(и это действительно сложно, поэтому я не рекомендую его):concat(substring(A, 1 div string(A) or 0), substring(B, 1 div not(string(A))) )
Вот полный пример для последнего случая , показывающий, что возвращает вызов
concat()
:XML документ :
<t> <p> <A>xxx</A> <B>yyy</B> </p> <p> <A/> <B>zzz</B> </p> </t>
Преобразование (просто выводит результаты вычисленных выражений):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="p"> <xsl:value-of select= "concat(substring(A, 1 div string(A) or 0), substring(B, 1 div not(string(A))) )"/> </xsl:template> </xsl:stylesheet>
Желаемый (правильный) результат:
xxx zzz
Вот еще один вариант, который использует другой
use
.XML Input
<Parent> <Child> <A>both</A> <B>both</B> <C>c</C> </Child> <Child> <A>a</A> <B></B> <C>c</C> </Child> <Child> <A></A> <B>b</B> <C>c</C> </Child> </Parent>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:strip-space elements="*"/> <xsl:key name="child" match="Child" use="(A[string()]|B[string()])[1]"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="/*"> <xsl:copy> <xsl:for-each select="Child[count(.|key('child',(A[string()]|B[string()])[1])[1])=1]"> <group key="{(A[string()]|B[string()])[1]}"> <xsl:apply-templates select="key('child',(A[string()]|B[string()])[1])"/> </group> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
Вывод XML
<Parent> <group key="both"> <Child> <A>both</A> <B>both</B> <C>c</C> </Child> </group> <group key="a"> <Child> <A>a</A> <B/> <C>c</C> </Child> </group> <group key="b"> <Child> <A/> <B>b</B> <C>c</C> </Child> </group> </Parent>