XSL查询问题:基于ID匹配无法正确提取CFGCode值
解决XSLT中按ID匹配填充CFGCode的问题
我来帮你搞定这个XSLT的匹配填充问题!先明确你的核心需求:
- 要通过
<plant>/<id>和<call>/parameters/parameter[@name='id']的文本值,精准关联对应的节点 - 将匹配到的
<call>节点里<column name='CFGCode'>的值,填入<plant>下的<cfg>/<id>标签中 - 批量处理所有
<plant>节点,保留原有结构的同时完成填充
先假设你的输入XML结构(如果实际结构有细微差异,可调整路径)
<root> <plant> <id>PLANT001</id> <cfg> <id></id> </cfg> </plant> <plant> <id>PLANT002</id> <cfg> <id></id> </cfg> </plant> <call> <parameters> <parameter name='id'>PLANT001</parameter> </parameters> <result> <column name='CFGCode'>CFG001</column> </result> </call> <call> <parameters> <parameter name='id'>PLANT002</parameter> </parameters> <result> <column name='CFGCode'>CFG002</column> </result> </call> </root>
修正后的XSLT代码
这里用<xsl:key>来建立高效的索引关联,比循环匹配更简洁可靠:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 建立键索引:以call中parameter[@name='id']的值为键,绑定对应的CFGCode节点 --> <xsl:key name="call-by-plant-id" match="call/result/column[@name='CFGCode']" use="../../parameters/parameter[@name='id']"/> <!-- 根节点模板 --> <xsl:template match="/"> <root> <!-- 处理所有plant节点 --> <xsl:apply-templates select="root/plant"/> </root> </xsl:template> <!-- 单个plant节点的处理模板 --> <xsl:template match="plant"> <plant> <!-- 复制plant原有的id节点 --> <xsl:copy-of select="id"/> <cfg> <!-- 通过key匹配当前plant的id,获取对应的CFGCode值 --> <id><xsl:value-of select="key('call-by-plant-id', id)"/></id> </cfg> <!-- 复制plant下除了id和cfg之外的其他节点(如果有的话) --> <xsl:copy-of select="node()[not(self::id or self::cfg)]"/> </plant> </xsl:template> </xsl:stylesheet>
关键逻辑说明
<xsl:key>索引:这是XSLT中关联节点的高效方式,把每个<call>里的CFGCode和对应的plant id绑定,后续可以通过id快速查找对应值,避免低效的循环匹配。- plant节点处理:遍历每个
<plant>时,用key('call-by-plant-id', id)直接找到与当前plant id匹配的CFGCode值,填充到<cfg>/<id>中。 - 节点保留:用
<xsl:copy-of>保留plant原有的其他节点,只修改需要填充的<cfg>/<id>部分。
预期输出结果
<root> <plant> <id>PLANT001</id> <cfg> <id>CFG001</id> </cfg> </plant> <plant> <id>PLANT002</id> <cfg> <id>CFG002</id> </cfg> </plant> </root>
适配调整提示
如果你的XML结构和示例有差异(比如<column>不在<result>下),只需要调整<xsl:key>里的match和use路径即可:
- 比如如果
<column>直接在<call>下,match改成call/column[@name='CFGCode'],use改成parameters/parameter[@name='id']。
内容的提问来源于stack exchange,提问作者user3529643
相关产品推荐
相关产品推荐

