Xml xpath根据子级的属性值删除节点

Xml xpath根据子级的属性值删除节点,xml,xslt,xpath,attributes,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="am

我有以下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>
我尝试了许多关于此查询的排列,但它会返回以下情况的每次出现:


我想我需要找到父母,但那是我知识枯竭的地方

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

例如

<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>
在此进行工作演示:

或者,您可以添加匹配的模板来代替

<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>

这将产生相同的输出

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

例如

<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>
在此进行工作演示:

或者,您可以添加匹配的模板来代替

<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>

这将产生相同的输出

下面是xpath,用于选择osm下不包含特定标记的所有节点:

//osm/*[not(.//tag[@k='addr:postcode'])]
以下是一些关于不放置的重要注意事项:

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

//element[not(.//child)]
请注意定位器:

将选择至少包含一个id为的子元素的所有元素!=一,

例如:

    <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>
将选择不包括id为3的单元格的第2行和第3行

    //row[.//cell[not(@id=3)]] 
将选择行1、2和3,但不选择至少有一个id不是3的单元格的4行


所以,放置not语句的位置很重要,因为它可能会完全改变XPath逻辑。

下面是XPath,用于选择osm下不包含特定标记的所有节点:

//osm/*[not(.//tag[@k='addr:postcode'])]
以下是一些关于不放置的重要注意事项:

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

//element[not(.//child)]
请注意定位器:

将选择至少包含一个id为的子元素的所有元素!=一,

例如:

    <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>
将选择不包括id为3的单元格的第2行和第3行

    //row[.//cell[not(@id=3)]] 
将选择行1、2和3,但不选择至少有一个id不是3的单元格的4行

所以,放置not语句的位置很重要,因为它可能会完全改变XPath逻辑