【问题标题】:Parsing XML with XPath in Python 3在 Python 3 中使用 XPath 解析 XML
【发布时间】:2022-01-01 01:09:36
【问题描述】:

我有以下 xml:

<document>
  <internal-code code="201">
    <internal-desc>Biscuits Wrapped</internal-desc>
    <top-grouping>Finished</top-grouping>
    <web-category>Biscuits</web-category>
    <web-sub-category>Biscuits (Wrapped)</web-sub-category>
  </internal-code>
  <internal-code code="202">
    <internal-desc>Biscuits Sweet</internal-desc>
    <top-grouping>Finished</top-grouping>
    <web-category>Biscuits</web-category>
    <web-sub-category>Biscuits (Sweets)</web-sub-category>
  </internal-code>
  <internal-code code="221">
    <internal-desc>Biscuits Savoury</internal-desc>
    <top-grouping>Finished</top-grouping>
    <web-category>Biscuits</web-category>
    <web-sub-category>Biscuits For Cheese</web-sub-category>
  </internal-code>
  ....
</document>

我已使用以下代码将其加载到树中:

try:
  groups = etree.parse(PRODUCT_GROUPS_XML_FILEPATH)
  root = groups.getroot()
  internalGroup = root.findall("./internal-code")
  LOG.append("[INFO] product groupings file loaded and parsed ok")
except Exception as e:
  LOG.append("[ERROR] PRODUCT GROUPINGS XML FILE ACCESS PROBLEM")
  LOG.append("[***TERMINATED***]")
  writelog()
  exit()

我想使用 XPath 找到正确的,然后能够访问该组的子节点。因此,如果我正在搜索内部代码 221 并想要网络类别,我会执行以下操作:

internalGroup.find("internal-code", 221).get("web-category").text

我没有使用 XML 和 Python 的经验,而且我多年来一直在关注它。非常感谢所有帮助。谢谢

【问题讨论】:

标签: python xml


【解决方案1】:

根据xml.etree.ElementTree 文档:

XPath 支持

此模块为 XPath 表达式提供有限支持 在树中定位元素。目标是支持一小部分 缩写语法;完整的 XPath 引擎不在 模块。

使用lxml:

>>> import lxml.etree as ET
>>>
>>> s = '''
... <document>
...   <internal-code code="201">
...     <internal-desc>Biscuits Wrapped</internal-desc>
...     <top-grouping>Finished</top-grouping>
...     <web-category>Biscuits</web-category>
...     <web-sub-category>Biscuits (Wrapped)</web-sub-category>
...   </internal-code>
...   <internal-code code="202">
...     <internal-desc>Biscuits Sweet</internal-desc>
...     <top-grouping>Finished</top-grouping>
...     <web-category>Biscuits</web-category>
...     <web-sub-category>Biscuits (Sweets)</web-sub-category>
...   </internal-code>
...   <internal-code code="221">
...     <internal-desc>Biscuits Savoury</internal-desc>
...     <top-grouping>Finished</top-grouping>
...     <web-category>Biscuits</web-category>
...     <web-sub-category>Biscuits For Cheese</web-sub-category>
...   </internal-code>
... </document>
... '''
>>>
>>> root = ET.fromstring(s)
>>> for text in root.xpath('.//internal-code[@code="221"]/web-category/text()'):
...     print(text)
...
Biscuits

【讨论】:

    【解决方案2】:

    虽然我是 lxml 的忠实粉丝(请参阅 falsetru 的回答),您需要完整的 xpath 支持,但标准库的 elementtree 实现确实支持足以满足您的需求:

    root.findtext('.//internal-code[@code="221]/web-category')
    

    这将返回第一个匹配元素的 text 属性,如果您确定代码 221 只会出现一次,这就足够了。如果还有更多并且您需要一份清单:

    [i.text for i in root.findall('.//internal-code[@code="221"]/web-category')]
    

    (请注意,这些示例也适用于 lxml)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多