如何遍历XML节点并重构指定XML结构?
XML节点重构解决方案
原始XML结构
<partyIdentification> <id>123</id> <schemeId>1111</schemeId> <!--GlobalIDs start from here--> <id>1234567</id> <schemeId>0011</schemeId> <id>7654321</id> <schemeId>0022</schemeId> <id>98765432</id> <schemeId>0033</schemeId> <id>13680123</id> <schemeId>0044</schemeId> </partyIdentification>
目标XML结构
<partyIdentification> <ID sid="1111">123</ID> <GlobalID sid="0011">1234567</GlobalID> <GlobalID sid="0022">7654321</GlobalID> <GlobalID sid="0033">98765432</GlobalID> <GlobalID sid="0044">13680123</GlobalID> </partyIdentification>
核心需求
- id与schemeId必须成对关联,每一组id对应紧随其后的schemeId
- 注释
<!--GlobalIDs start from here-->之前的id/schemeId组,要转换成<ID>节点,sid属性值对应原schemeId的内容 - 注释之后的id/schemeId组,要转换成
<GlobalID>节点,sid属性值同样对应原schemeId的内容
已尝试的XSLT代码
<xsl:template match="partyIdentification/id[following-sibling::comment()[1]]"> <xsl:variable name="IDs"> <xsl:copy-of select="."/> </xsl:variable> <xsl:variable name="IDsRestructuring"> <xsl:for-each select="$IDs/id"> <id sid="{following-sibling::schemeId[1]}"><xsl:value-of select="normalize-space(.)"/></id> </xsl:for-each> </xsl:variable> <xsl:for-each select="exsl:node-set($IDsRestructuring)/id"> <ID schemeID="{@sid}"><xsl:value-of select="."/></ID> </xsl:for-each> </xsl:template>
可行解决方案
直接通过定位目标注释,分别处理前后的id节点即可,无需使用exsl:node-set绕弯。以下是完整的XSLT代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 匹配并保留partyIdentification节点结构 --> <xsl:template match="partyIdentification"> <xsl:copy> <!-- 处理注释前的id节点,生成ID元素 --> <xsl:for-each select="id[following-sibling::comment()[1][contains(.,'GlobalIDs start from here')]]"> <ID sid="{following-sibling::schemeId[1]}"> <xsl:value-of select="normalize-space(.)"/> </ID> </xsl:for-each> <!-- 处理注释后的id节点,生成GlobalID元素 --> <xsl:for-each select="comment()[contains(.,'GlobalIDs start from here')]/following-sibling::id"> <GlobalID sid="{following-sibling::schemeId[1]}"> <xsl:value-of select="normalize-space(.)"/> </GlobalID> </xsl:for-each> </xsl:copy> </xsl:template> <!-- 忽略原有的schemeId节点和注释节点,避免输出冗余内容 --> <xsl:template match="schemeId | comment()"/> </xsl:stylesheet>
代码说明
- 主模板匹配
partyIdentification节点,先复制节点本身,再处理内部内容 - 第一个
for-each精准定位到目标注释之前的id节点,每个id节点取紧随其后的第一个schemeId值作为sid属性,生成<ID>节点 - 第二个
for-each选中目标注释之后的所有id节点,同样取对应schemeId值生成<GlobalID>节点 - 最后通过模板忽略原有的schemeId和注释节点,确保输出只保留需要的结构
内容的提问来源于stack exchange,提问作者Susheel Kumar
相关产品推荐
相关产品推荐

