xpath根据子属性值删除节点

时间:2017-10-17 21:51:11

标签: xml xslt xpath attributes

我有这个xml代码:

<osm>
  <count>
    <tag k="nodes" v="608"/>   
  </count>
  <node>
    <tag k="addr:housenumber" v="5-10"/>
    <tag k="addr:postcode" v="BA1 2BX"/>
  </node>
  <way>
    <tag k="amenity" v="nightclub"/>
    <tag k="facebook" v="https://www.facebook.com"/>
  </way>
  <node>
    <tag k="amenity" v="cafe"/>
    <tag k="addr:postcode" v="BS3 2BX"/> 
  </node>
  <node>
    <tag k="amenity" v="school"/>
    <tag k="facebook" v="https://www.facebook.com"/>
  </node>
  <way>
    <tag k="amenity" v="church"/>
    <tag k="addr:postcode" v="BAX 5RT"/>   
  </way>
</osm>

我需要删除<osm>下面包含<tag>节点的所有节点,其中属性k的值为'addr:postcode'

<osm>
  <count>
    <tag k="nodes" v="608"/>   
  </count>
  <way>
    <tag k="amenity" v="nightclub"/>
    <tag k="facebook" v="https://www.facebook.com"/>
  </way>
  <node>
    <tag k="amenity" v="school"/>
    <tag k="facebook" v="https://www.facebook.com"/>
  </node>
</osm>

我已尝试过围绕此查询的许多排列,但它会返回<tag>的每次出现:

<xsl:apply-templates select="osm/*/tag[not(@k='addr:postcode')]"> 

我认为我需要找到父母,但这就是我的知识耗尽的地方。

2 个答案:

答案 0 :(得分:3)

你是对的;您需要选择tag的父级。为此,只需选择*并将tag放入谓词中。

示例...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="osm">
    <xsl:copy>
      <xsl:apply-templates select="*[not(tag/@k='addr:postcode')]"/>      
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

此处的演示演示:http://xsltransform.net/pNmBy23

或者,您可以添加匹配的模板......

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[tag/@k='addr:postcode']"/>

</xsl:stylesheet>

这将产生相同的输出。 (http://xsltransform.net/pNmBy23/1

答案 1 :(得分:1)

这是xpath,用于选择install( FILES somescript.sh PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ DESTINATION /some/destination ) 下不包含特定标记的所有节点:

osm

以下是//osm/*[not(.//tag[@k='addr:postcode'])] 展示位置的一些重要说明:

  

搜索不包含子元素的元素(任何级别   下面)使用模式:

not()

请注意定位器:

//element[not(.//child)]
     

将选择包含至少1个ID为!= 1的子项的所有元素。

所以在例子中:

    //element[.//child[not(@id=1)]]
    <row class="row1">
    <cell id=1/>
    <cell id=2/>
    <cell id=3/>
    </row>
    <row class="row2">
    <cell id=1/>
    <cell id=2/>
    </row>
    <row class="row3">
    <cell id=1/>
    <cell id=2/>
    </row>
    <row class="row4">
    <cell id=3/>
    </row>
     

将选择第2行和第3行(不包含id = 3的单元格的行)

     //row[not(.//cell[@id=3])]  
     

将选择第1,2和3行,但不包括第4行(至少包含一个ID不是3的单元格的行)

所以放置 //row[.//cell[not(@id=3)]] 语句非常重要,因为它可能完全改变XPath逻辑。