如何在XSL中除指定元素外将其余XML元素放入二级节点(非硬编码)
通用XSL解决方案:将可变标签包裹到Payload中
需求说明
- 输入XML里
<value>和<UniqueId>是固定存在的标签 - 需要把
<value>节点下除<UniqueId>之外的所有可变标签,统一放到<Payload>标签内部
输入XML
<value> <UniqueId>160052-ASDF</UniqueId> <ShipmentId>160052</ShipmentId> <PickListNo>160052_1</PickListNo> </value>
期望输出XML
<value> <UniqueId>160052-ASDF</UniqueId> <Payload> <ShipmentId>160052</ShipmentId> <PickListNo>160052_1</PickListNo> </Payload> </value>
现有硬编码XSL(不通用)
这种写法需要硬编码所有可变标签名,无法适配标签变化的场景:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <value> <UniqueId> <xsl:value-of select="/value/UniqueId"/> </UniqueId> <Payload> <ShipmentId> <xsl:value-of select="/value/ShipmentId"/> </ShipmentId> <PickListNo> <xsl:value-of select="/value/PickListNo"/> </PickListNo> </Payload> </value> </xsl:template> </xsl:stylesheet>
尝试的失败写法
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <value> <UniqueId> <xsl:value-of select="/value/UniqueId"/> </UniqueId> <Payload> <xsl:for-each select="*[not(self::UniqueId)]"> <xsl:copy-of select="."/> </xsl:for-each> </Payload> </value> </xsl:template> </xsl:stylesheet>
失败原因:当前上下文是根节点/,*匹配的是根节点下的<value>节点,而非<value>内部的子节点,导致无法选中目标标签。
通用解决方案
方案一(推荐:更简洁直观)
直接匹配<value>节点,切换上下文后简化选择逻辑:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/value"> <value> <!-- 直接复制原有的UniqueId标签及内容 --> <xsl:copy-of select="UniqueId"/> <!-- 创建Payload标签,复制所有非UniqueId的子节点 --> <Payload> <xsl:copy-of select="*[not(self::UniqueId)]"/> </Payload> </value> </xsl:template> </xsl:stylesheet>
方案二(基于原写法修正路径)
在根节点匹配模板里,修正for-each的选择路径:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <value> <UniqueId> <xsl:value-of select="/value/UniqueId"/> </UniqueId> <Payload> <!-- 明确选择/value下的非UniqueId子节点 --> <xsl:for-each select="/value/*[not(self::UniqueId)]"> <xsl:copy-of select="."/> </xsl:for-each> </Payload> </value> </xsl:template> </xsl:stylesheet>
两种方案都无需硬编码任何可变标签名,能自动适配<value>下除<UniqueId>外的所有子标签。
内容的提问来源于stack exchange,提问作者mmmrbm
相关产品推荐
相关产品推荐

