Xml 使用XSLT筛选未引用的成员节点
OpenStreetMapXML文档由一组“节点”元素和一组“方式”元素组成 “节点”元素可以(可选)嵌套“标记”元素 “方式”元素由“节点”元素的有序列表组成,由嵌套元素“nd”引用,其属性“ref”指向“节点”元素处的属性“id” 这里有一个例子:Xml 使用XSLT筛选未引用的成员节点,xml,xslt,Xml,Xslt,OpenStreetMapXML文档由一组“节点”元素和一组“方式”元素组成 “节点”元素可以(可选)嵌套“标记”元素 “方式”元素由“节点”元素的有序列表组成,由嵌套元素“nd”引用,其属性“ref”指向“节点”元素处的属性“id” 这里有一个例子: <?xml version="1.0" encoding="UTF-8"?> <osm version="0.6" generator="CGImap 0.0.2"> <node id="1726631203"
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="CGImap 0.0.2">
<node id="1726631203" lat="50.8500083" lon="4.3553223" visible="true" version="6" changeset="9938190" timestamp="2011-11-24T22:05:32Z"/>
...
<way id="160611697" user="toSc" uid="246723" visible="true" version="1" changeset="11385198" timestamp="2012-04-22T14:57:19Z">
<nd ref="1726631203"/>
<nd ref="1726631223"/>
<nd ref="1726631213"/>
<nd ref="1726631205"/>
<nd ref="1726631185"/>
<nd ref="1726631203"/>
</way>
...
</osm>
...
...
我的问题是,如何使用XSLT进行以下转换
- 筛选所有未被any way元素引用的节点元素李>
- 筛选引用源xml文档中未包含的节点元素的方式
- 将属性“visible”更改为“false”,更改为任何没有“tag”子元素的“node”元素李>
任何其他元素都应该保留在生成的xml中。类似的内容应该可以工作:
<xsl:for-each select="//osm/node">
<xsl:if test="//osm/way/nd[@ref=current()/@id]">
<xsl:copy-of select=".">
</xsl:if>
</xsl:for-each>
诀窍在于,如果xpath表达式返回一个或多个结果,则if节点中的测试将返回true。您可以使用相同的技术检查标记属性是否存在。不幸的是,当您需要更改属性时,您需要手动复制其他属性(xsl:copy除了visible属性之外的所有子元素,而不是简单地使用xsl:copy of)。这似乎有效:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="node">
<xsl:if test="//osm/way/nd[@ref=current()/@id]">
<xsl:choose>
<xsl:when test="tag">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:copy-of select="@*[not(local-name(.) = 'visible')]"/>
<xsl:attribute name="visible">false</xsl:attribute>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
假的
xsl:if测试是从前面的答案复制而来的,并消除了未引用的节点
当缺少标记子项时,xsl:choose中的位将visible属性设置为false。这是一种更改属性值的方法,无需单独复制所有属性;但它忽略除标记之外的任何子元素
我还没有提到过滤方式元素
我的问题是,如何使用XSLT执行以下操作
转变
- 筛选所有未被any way元素引用的节点元素
- 筛选引用源xml文档中未包含的节点元素的方式
- 将属性“visible”更改为“false”,更改为任何没有“tag”子元素的“node”元素
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kND-By-Ref" match="way/nd" use="@ref"/>
<xsl:key name="kNodeById" match="node" use="@id"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node[not(key('kND-By-Ref', @id))]"/>
<xsl:template match="way[nd[not(key('kNodeById', @ref))]]"/>
<xsl:template match="node[not(tag)]/@visible">
<xsl:attribute name="visible">false</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
说明:
<osm version="0.6" generator="CGImap 0.0.2">
<node id="1726631203" lat="50.8500083" lon="4.3553223"
visible="true" version="6" changeset="9938190" timestamp="2011-11-24T22:05:32Z">
<tag/>
</node>
<node id="1726631223" lat="50.8500083" lon="4.3553223"
visible="false" version="6" changeset="9938190" timestamp="2011-11-24T22:05:32Z"/>
<way id="160611697" user="toSc" uid="246723" visible="true"
version="1" changeset="11385198" timestamp="2012-04-22T14:57:19Z">
<nd ref="1726631203"/>
<nd ref="1726631223"/>
</way>
</osm>
id
属性方便有效地查找node
s,并通过其ref
属性方便有效地查找nd
s谢谢你如此完整的回答@Dimitre!。试着理解这一逻辑:在声明键时,为什么要在匹配条件中写入“way/nd”和“node”,而不是“/osm/way/nd”和“/osm/node”?我的问题是,我不知道此行“key”函数的当前上下文路径在哪里:换句话说,在我看来,key函数中的路径应该是绝对的(正如我上面所写的)或者在node元素的上下文中,因为它是由“match”条件匹配的元素。@Sergio:match属性中的表达式是“match pattern”,通常是一个简短的相对XPath表达式。只有在需要消除歧义时才需要指定祖先。在这种情况下,我可以只使用
match=“nd”
,因为nd
元素只显示为way
的子元素。如果他们可能是两个名字不同的父母的孩子,则需要way/nd
match=“nd”
表示(与xsl:template
上指定的mtch模式完全相同):匹配当前节点的任何子节点,其名称(子节点的名称)为“nd”
。您需要阅读有关匹配模式的内容才能更好地理解它们。我明白了,在上一个模板中,您为什么要编写而不是只编写?。在第二种情况下,您不会发现所有没有嵌套“标记”的“节点”元素元素?。感谢您的澄清。@Sergio:我这样做是因为我想匹配属性本身——而不是保存它的元素,标识模板负责元素——唯一必须更改的节点是属性。
<osm version="0.6" generator="CGImap 0.0.2">
<node id="1726631203" lat="50.8500083" lon="4.3553223"
visible="true" version="6" changeset="9938190" timestamp="2011-11-24T22:05:32Z">
<tag/>
</node>
<node id="1726631223" lat="50.8500083" lon="4.3553223"
visible="false" version="6" changeset="9938190" timestamp="2011-11-24T22:05:32Z"/>
<way id="160611697" user="toSc" uid="246723" visible="true"
version="1" changeset="11385198" timestamp="2012-04-22T14:57:19Z">
<nd ref="1726631203"/>
<nd ref="1726631223"/>
</way>
</osm>