如何使用XPath将子节点属性合并至父节点?
需求说明
需要编写转换逻辑实现:将XML中<player>节点的子节点<stats>的所有属性合并到父节点<player>中,并移除<stats>子节点。
原始XML示例
<player uni="04" name="John Doe" gp="1" gs="1" pos="G"> <stats fgm="0" fga="3" fgm3="0" fga3="1" ftm="2" fta="2" tp="2" blk="0" stl="0" ast="0" min="23" oreb="2" dreb="2" treb="4" pf="2" tf="0" to="3" dq="0"></stats> </player>
尝试的XPath表达式
//team[1]/player[@*] | ../stats[@*]
当前得到的结果
<player uni="03" name="John Doe" gp="1" gs="1" pos="G"> <stats fgm="0" fga="3" fgm3="0" fga3="0" ftm="10" fta="10" tp="10" blk="0" stl="1" ast="1" min="33" oreb="2" dreb="2" treb="4" pf="2" tf="0" to="1" dq="0"> </stats> </player>
期望得到的结果
<player uni="03" name="John Doe" gp="1" gs="1" pos="G" fgm="0" fga="3" fgm3="0" fga3="0" ftm="10" fta="10" tp="10" blk="0" stl="1" ast="1" min="33" oreb="2" dreb="2" treb="4" pf="2" tf="0" to="1" dq="0"></player>
解决方案
首先明确:XPath是查询语言,只能选择节点或属性,无法直接修改XML结构(添加属性、移除节点)。要实现属性合并和节点移除,需要使用XSLT(可扩展样式表语言转换)。
以下是实现需求的XSLT代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份模板:原样复制未被特殊匹配的节点和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理player节点,合并stats属性并移除stats节点 --> <xsl:template match="player"> <xsl:copy> <!-- 复制player自身的所有属性 --> <xsl:apply-templates select="@*"/> <!-- 复制stats节点的所有属性到player上 --> <xsl:apply-templates select="stats/@*"/> <!-- 复制player除stats外的其他子节点 --> <xsl:apply-templates select="node()[not(self::stats)]"/> </xsl:copy> </xsl:template> <!-- 匹配stats节点,不输出,实现移除效果 --> <xsl:template match="stats"/> </xsl:stylesheet>
代码说明
- 身份模板保证XML中未被特殊处理的内容原样保留,不影响其他节点结构;
- 针对
<player>的模板完成核心逻辑:先复制自身属性,再追加<stats>的所有属性,最后保留除<stats>外的其他子节点; - 最后一个模板匹配
<stats>节点但不输出,直接移除该节点。
用该XSLT处理原始XML,即可得到你期望的结果。
内容的提问来源于stack exchange,提问作者chrissabato
相关产品推荐
相关产品推荐

