【问题标题】:I have some problems with xpath in python我在 python 中的 xpath 有一些问题
【发布时间】:2017-01-06 16:26:33
【问题描述】:

我正在尝试使用 xpath 查询和 lxml 模块获取不同的值。 所以我的代码似乎工作正常,但我有两个我无法解决的问题。 xml

<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" generator="osmconvert 0.8.5">
        <node id="429459476" lat="55.6091243" lon="37.7270414" version="2" timestamp="2012-02-20T18:13:50Z" changeset="10743203" uid="210173" user="osmmaker">
        <tag k="amenity" v="library"/>
        <tag k="name" v="Детская библиотека №101"/>
        <tag k="opening_hours" v="Mo-Fr 12:00-18:00; Sa 12:00-17:00"/>
        <tag k="phone" v="+7-495-3995297"/>
    </node>
    <node id="448176571" lat="55.6098905" lon="37.7317767" version="2" timestamp="2009-11-03T16:02:27Z" changeset="3025778" uid="75496" user="navigARTor">
        <tag k="highway" v="bus_stop"/>
        <tag k="name" v="Воронежская улица"/>
    </node>
    <node id="448176571" lat="55.6098905" lon="37.7317767" version="2" timestamp="2009-11-03T16:02:27Z" changeset="3025778" uid="75496" user="navigARTor">
        <tag k="highway" v="bus_stop"/>
        <tag k="name" v="Воронежская улица"/>
    </node>
</osm>

Python 代码

from lxml import etree
tree = etree.parse('out.xml')
tags = tree.xpath('./node[tag[not(@k = preceding::tag/@k)]]')
with open('10.xml','w') as f:
    for tag in tags:
          f.write(etree.tostring(tag,pretty_print=True).decode())

xpath 查询后的 XML

<node id="429459476" lat="55.6091243" lon="37.7270414" version="2" timestamp="2012-02-20T18:13:50Z" changeset="10743203" uid="210173" user="osmmaker">
        <tag k="amenity" v="library"/>
        <tag k="name" v="&#1044;&#1077;&#1090;&#1089;&#1082;&#1072;&#1103; &#1073;&#1080;&#1073;&#1083;&#1080;&#1086;&#1090;&#1077;&#1082;&#1072; &#8470;101"/>
        <tag k="opening_hours" v="Mo-Fr 12:00-18:00; Sa 12:00-17:00"/>
        <tag k="phone" v="+7-495-3995297"/>
    </node>


<node id="448176571" lat="55.6098905" lon="37.7317767" version="2" timestamp="2009-11-03T16:02:27Z" changeset="3025778" uid="75496" user="navigARTor">
        <tag k="highway" v="bus_stop"/>
        <tag k="name" v="&#1042;&#1086;&#1088;&#1086;&#1085;&#1077;&#1078;&#1089;&#1082;&#1072;&#1103; &#1091;&#1083;&#1080;&#1094;&#1072;"/>
    </node>

问题 #1

如何获取完整的 xml 文档,例如:

<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" generator="osmconvert 0.8.5">
        <node id="429459476" lat="55.6091243" lon="37.7270414" version="2" timestamp="2012-02-20T18:13:50Z" changeset="10743203" uid="210173" user="osmmaker">
        <tag k="amenity" v="library"/>
        <tag k="name" v="&#1044;&#1077;&#1090;&#1089;&#1082;&#1072;&#1103; &#1073;&#1080;&#1073;&#1083;&#1080;&#1086;&#1090;&#1077;&#1082;&#1072; &#8470;101"/>
        <tag k="opening_hours" v="Mo-Fr 12:00-18:00; Sa 12:00-17:00"/>
        <tag k="phone" v="+7-495-3995297"/>
    </node>
<node id="448176571" lat="55.6098905" lon="37.7317767" version="2" timestamp="2009-11-03T16:02:27Z" changeset="3025778" uid="75496" user="navigARTor">
        <tag k="highway" v="bus_stop"/>
        <tag k="name" v="&#1042;&#1086;&#1088;&#1086;&#1085;&#1077;&#1078;&#1089;&#1082;&#1072;&#1103; &#1091;&#1083;&#1080;&#1094;&#1072;"/>
    </node>
</osm>

问题 #2 以及如何摆脱这种胡言乱语

v="&#1042;&#1086;&#1088;&#1086;&#1085;&#1077;&#1078;&#1089;&#1082;&#1072;&#1103; &#1091;&#1083;&#1080;&#1094;&#1072

附:对不起我的英语不好,希望你能理解

【问题讨论】:

  • abacadabra 是您的原始西里尔文字。你想摆脱它(意思是:“删除它”),还是你想把它看作是常规的西里尔文字? (如果是这种情况,有标准的解决方案可以这样做。寻找“将 HTML 实体转换为文本”。)

标签: python xml xpath lxml


【解决方案1】:

考虑 XPath 的兄弟XSLT 来操作您的源 XML。 XPath 非常适合解析文档的选定区域,而 XSLT 是一种专门用于转换文档的语言。具体来说,您需要更多的是Muenchian Method,您可以在其中按元素/属性值(使用xsl:key)对文档进行索引,以进行分组以返回不同的值。这里我们使用node/@id

Python 的 lxml 模块可以处理 XSLT 1.0 脚本。由于此类脚本是格式良好的 XML 文件,因此它们可以从文件中解析或作为嵌入字符串进行解析。走这条路的另一个原因是保留 unicode,这是您原始输出的挑战,因为 etree.tostring() 方法正在为特殊的西里尔字符呈现 character entities

XSLT 脚本(另存为.xsl)

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

 <xsl:key name="nodekey" match="node" use="@id" />

  <xsl:template match="/osm">   
   <xsl:copy>
     <xsl:copy-of select="@*"/>
     <xsl:for-each select="node[count(. | key('nodekey', @id))]">
      <xsl:copy>        
        <xsl:copy-of select="@*|*"/>
      </xsl:copy>
    </xsl:for-each>
   </xsl:copy>
  </xsl:template>

</xsl:transform>

Python脚本

from lxml import etree

xml = etree.parse('Input.xml')
xsl = etree.parse('XSLTScript.xsl')

transform = etree.XSLT(xsl)
newdom = transform(xml)

with open('Output.xml', 'wb') as f:
    f.write(newdom)

XML输出

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="osmconvert 0.8.5">
  <node id="429459476" lat="55.6091243" lon="37.7270414" version="2" timestamp="2012-02-20T18:13:50Z" changeset="10743203" uid="210173" user="osmmaker">
    <tag k="amenity" v="library"/>
    <tag k="name" v="Детская библиотека №101"/>
    <tag k="opening_hours" v="Mo-Fr 12:00-18:00; Sa 12:00-17:00"/>
    <tag k="phone" v="+7-495-3995297"/>
  </node>
  <node id="448176571" lat="55.6098905" lon="37.7317767" version="2" timestamp="2009-11-03T16:02:27Z" changeset="3025778" uid="75496" user="navigARTor">
    <tag k="highway" v="bus_stop"/>
    <tag k="name" v="Воронежская улица"/>
  </node>
</osm>

【讨论】:

  • 我想这正是我要找的东西
猜你喜欢
  • 2023-02-13
  • 2018-05-21
  • 2022-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
  • 1970-01-01
相关资源
最近更新 更多