XSLT处理XML:移除重复DeliveryNr及空TripOverview元素求助
XSLT解决方案:去重DeliveryNr并清理空TripOverview
处理逻辑
要同时实现两个需求,需先筛选有效节点再去重:
- 先排除无DropItem或DropItems为空的
TripOverview - 对剩余节点按
DeliveryNr去重,仅保留首次出现的条目
完整XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:strip-space elements="*"/> <!-- 定义键:仅索引包含有效DropItem的TripOverview的DeliveryNr --> <xsl:key name="deliveryKey" match="TripOverview[DropItems/DropItem]" use="DeliveryNr"/> <!-- 复制根节点结构 --> <xsl:template match="/"> <xsl:copy> <xsl:apply-templates select="*"/> </xsl:copy> </xsl:template> <!-- 处理Trips容器,筛选符合条件的子节点 --> <xsl:template match="Trips"> <xsl:copy> <!-- 双条件过滤:有有效DropItem + 是该DeliveryNr的首次出现 --> <xsl:apply-templates select="TripOverview[DropItems/DropItem][generate-id() = generate-id(key('deliveryKey', DeliveryNr)[1])]"/> </xsl:copy> </xsl:template> <!-- 复制符合条件的TripOverview及其所有子节点 --> <xsl:template match="TripOverview"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 默认模板:复制所有其他节点和属性 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码说明
- 键定义:
deliveryKey仅匹配包含至少一个DropItem的TripOverview,确保去重范围只针对有效节点 - 筛选逻辑:在
Trips模板中通过两个条件过滤:DropItems/DropItem:确保TripOverview有非空的DropItems(存在DropItem子元素)generate-id() = generate-id(key('deliveryKey', DeliveryNr)[1]):仅保留每个DeliveryNr对应的第一个有效TripOverview
- 默认模板:保证所有其他节点(如
DeliveryNr、DropItem等)原封不动复制
你之前方法的问题原因
- 非链式方法可能仅做了去重,但未提前过滤空
TripOverview,导致无DropItem的节点虽被去重但仍残留 - 链式方法若步骤顺序错误(先去重再过滤)或过滤逻辑不严谨(仅判断
DropItems是否存在,未检查是否有DropItem子元素),会出现无输出变化的情况
输入输出示例
输入XML
<Trips> <TripOverview> <DeliveryNr>DEL-001</DeliveryNr> <DropItems> <DropItem> <Address>Main St 1</Address> </DropItem> </DropItems> </TripOverview> <TripOverview> <DeliveryNr>DEL-001</DeliveryNr> <DropItems/> </TripOverview> <TripOverview> <DeliveryNr>DEL-002</DeliveryNr> <DropItems/> </TripOverview> <TripOverview> <DeliveryNr>DEL-003</DeliveryNr> <DropItems> <DropItem> <Address>Oak Ave 5</Address> </DropItem> </DropItems> </TripOverview> <TripOverview> <DeliveryNr>DEL-003</DeliveryNr> <DropItems> <DropItem> <Address>Pine Rd 10</Address> </DropItem> </DropItems> </TripOverview> </Trips>
输出XML
<Trips> <TripOverview> <DeliveryNr>DEL-001</DeliveryNr> <DropItems> <DropItem> <Address>Main St 1</Address> </DropItem> </DropItems> </TripOverview> <TripOverview> <DeliveryNr>DEL-003</DeliveryNr> <DropItems> <DropItem> <Address>Oak Ave 5</Address> </DropItem> </DropItems> </TripOverview> </Trips>
内容的提问来源于stack exchange,提问作者Mike Dole
相关产品推荐
相关产品推荐

