在XSLT 3.0(Saxon-HE 10.9)中无法访问解析后未转义XML子元素
问题
使用Saxon-HE 10.9搭配XSLT 3.0,尝试转换嵌入在大型XML文件中的未转义XML字符串,已通过以下模板实现解析输出:
<xsl:template match="INTERNAL_MATCH" mode="dataset"> <xsl:variable name="unescapedXML" select="parse-xml(.)"/> <TESTVAL> <xsl:element name="output-params2"> <xsl:copy-of select="//$unescapedXML" /> </xsl:element> </TESTVAL> </xsl:template>
输出结果如下:
<TESTVAL> <output-params2> <product ism:ownerProducer="USA"> <name>Test Product</name> <shortName>TP</shortName> <base type="testtype" id="1235"/> <base type="testtype2" id="1236"/> </product> </output-params2> </TESTVAL>
需要访问该输出的子节点,筛选出type='testtype'的base元素并将其id存储为变量,但尝试使用<xsl:copy-of select="//$unescapedXML/product/base" />无返回结果,该如何实现?
解决方案
问题根源
原XPath表达式//$unescapedXML/product/base写法错误:$unescapedXML是parse-xml(.)返回的文档节点,XPath中不能将变量直接放在//轴之后,正确的写法是从文档节点出发,使用相对路径或绝对路径选择子节点。
实现步骤
- 筛选目标
base元素:使用$unescapedXML//product/base[@type='testtype']定位符合条件的元素(//表示从文档节点开始递归查找所有product下的base元素,[@type='testtype']是筛选条件)。 - 存储
id属性值到变量:通过@id获取属性值,存入变量。
修改后的模板示例
<xsl:template match="INTERNAL_MATCH" mode="dataset"> <xsl:variable name="unescapedXML" select="parse-xml(.)"/> <!-- 筛选type='testtype'的base元素 --> <xsl:variable name="targetBase" select="$unescapedXML//product/base[@type='testtype']"/> <!-- 存储该元素的id属性值 --> <xsl:variable name="targetId" select="$targetBase/@id"/> <!-- 可选:验证输出 --> <TESTVAL> <output-params2> <xsl:copy-of select="$targetBase"/> <selected-id><xsl:value-of select="$targetId"/></selected-id> </output-params2> </TESTVAL> </xsl:template>
补充说明
- 如果
product是解析后XML的根元素,可使用更高效的路径:$unescapedXML/*/base[@type='testtype'](避免递归查找)。 - 若存在多个符合条件的
base元素,$targetId会返回所有匹配的id值序列,可根据需求用$targetId[1]取第一个值。
内容的提问来源于stack exchange,提问作者Alex Elkman
相关产品推荐
相关产品推荐

