如何比对XML所有way节点首尾nd的ref属性并返回仅出现一次的值
XSLT筛选唯一端点节点解决方案
需求说明
比对所有<way>节点下第一个和最后一个<nd>节点的ref属性,仅返回ref值在所有首尾节点中唯一出现的<nd>节点。
现有XML结构
<osm> <way> <nd ref="1"/> <nd ref="2"/> <nd ref="3"/> <tag k="highway"/> </way> <way> <nd ref="2"/> <nd ref="3"/> <nd ref="4"/> <tag k="highway"/> </way> <way> <nd ref="4"/> <nd ref="6"/> <nd ref="1"/> <tag k="highway"/> </way> <way> <nd ref="2"/> <nd ref="4"/> <nd ref="7"/> <tag k="highway"/> </way> </osm>
预期输出
<nd ref="3"/> <nd ref="7"/>
正确实现代码(XSLT 2.0)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> <xsl:template match="/"> <!-- 收集所有way的首尾nd节点 --> <xsl:variable name="allEndNodes" select="osm/way/*[self::nd and (position()=1 or position()=last())]"/> <!-- 按ref分组,筛选仅出现1次的节点 --> <xsl:for-each-group select="$allEndNodes" group-by="@ref"> <xsl:if test="count(current-group()) = 1"> <xsl:copy-of select="."/> </xsl:if> </xsl:for-each-group> </xsl:template> </xsl:stylesheet>
逻辑说明
- 先通过
$allEndNodes变量收集所有<way>下的第一个和最后一个<nd>节点,排除中间的<nd>和<tag>节点 - 用XSLT 2.0的分组特性按
ref属性对所有端点节点分组 - 筛选分组大小为1的节点,即
ref值唯一的节点,直接拷贝输出即可
内容的提问来源于stack exchange,提问作者DaveF
相关产品推荐
相关产品推荐

