Перебирать узлы, содержащие CDATA, и объединять их, а также как извлекать конкретные данные из сцепленных данных.
Я новичок в XSLT и мне нужно решить неприятную проблему, и у меня нет никаких изменений, чтобы решить ее. Следующий пример описывает мою проблему:
<a>
<b1><![CDATA[<CdtrRefInf><Issr>XXX</Issr></Tp><Ref>123456123]]></b1>
<b2><![CDATA[193</Ref></CdtrRefInf>]]></b2>
</a>
Ожидаемый результат должен быть:
<a>
<b1>123456123193<b1>
</a>
Мне нужно перебрать элементы b1 и b2 и объединить содержимое в переменную. Затем мне нужно взять содержимое элемента Ref и поместить его в элемент b1. Следующий код объединяет содержимое полей b1 и b2 вместе. Но как это поставить в вышеуказанном формате?????
<xsl:template match="/*">
<xsl:variable name="vMyVars">
<xsl:apply-templates select="b1 | b2 " mode="vMyVars"/>
</xsl:variable>
<xsl:value-of select="substring($vMyVars, -1, string-length($vMyVars))"/>
</xsl:template>
<xsl:template match="*" mode="vMyVars"/>
<xsl:template match="*[normalize-space()]" mode="vMyVars">
<xsl:value-of select="."/>
<!--<xsl:text>, </xsl:text>-->
</xsl:template>
Любой совет приветствуется. С уважением Дирк
1 ответ
Для этого вам понадобится XPath 3.0 (XSLT 3.0). Просто используйте:
parse-xml(concat(/*/b1, /*/b2))/*/Ref/text()
Вам также необходимо исправить текст внутри разделов CDATA - он содержит </Tp>
- закрывающий тег, который не имеет соответствующего начального тега. Я исправил это, чтобы: <Tp/>
,
С этим исправлением к предоставленному документу XML теперь:
<a>
<b1><![CDATA[<CdtrRefInf><Issr>XXX</Issr></Tp><Ref>123456123]]></b1>
<b2><![CDATA[193</Ref></CdtrRefInf>]]></b2>
</a>
Оценка приведенного выше выражения XPath 3.0 в приведенном выше документе XML дает желаемый, правильный результат:
123456123193
Я проверил это с помощью BaseX, используя этот XQuery 3.0:
let $top :=
<a>
<b1><![CDATA[<CdtrRefInf><Issr>XXX</Issr><Tp/><Ref>123456123]]></b1>
<b2><![CDATA[193</Ref></CdtrRefInf>]]></b2>
</a>
return
parse-xml(concat($top/b1, $top/b2))/*/Ref/text()
II. Решение в XSLT 2.0
XSLT 2.0 не предоставляет простой функции или инструкции для разбора строки в документ / фрагмент XML.
В Saxon можно использовать функцию расширения saxon:parse():
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:saxon="http://saxon.sf.net/">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:copy-of select="saxon:parse(concat(/*/b1, /*/b2))/*/Ref/text()"/>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование выполняется с помощью Saxon 9.1.07 в предоставленном XML-документе:
<a>
<b1><![CDATA[<CdtrRefInf><Issr>XXX</Issr><Tp/><Ref>123456123]]></b1>
<b2><![CDATA[193</Ref></CdtrRefInf>]]></b2>
</a>
желаемый, правильный результат получается:
123456123193