[Python] XPath 教學

程式語言:Python
Package:xml.etree.ElementTree

ElementTree 官方文件
測試網站

功能:解析 XML
ET 並未完全支援 XPath,以下內容只說明 ET 支援的部分
import xml.etree.ElementTree as ET

tree = ET.parse('data.xml')
root = tree.getroot()
# root[0] 表示第一個 child
# root[1][2] 表示第二個 child 的 第三個 child

# root = ET.fromstring(data_as_string)

範例

<?xml version="1.0" encoding="UTF-8"?>

<根>
    <孩子A 姓名="大頭王">
        <目前地點>大頭王家</目前地點>
        <子孫C 姓名="大頭">
            <目前地點>大頭王家</目前地點>
        </子孫C>
    </孩子A>
    <孩子B 姓名="王老">
        <目前地點>家中的田</目前地點>
        <子孫D 姓名="老王">
            <目前地點>鄰居家</目前地點>
        </子孫D>
    </孩子B>
</根>

語法

  • tag
    • child 節點名字,需完全一樣,且只會找到 孩子代
    • 例子
      • root.find('孩子')
        • None
      • root.find('孩子A')
        • <Element '孩子A' at 0x00000000037E5B38>
      • root.find('子孫C')
        • None
  • '*'
    • 任意節點
    • 例子
      • root.find('*/子孫D')
        • <Element '子孫D' at 0x00000000037EB098>
  • '/'
    • 位置分隔線,需搭配節點名字
    • 例子
      • root.find('./孩子A')
        • <Element '孩子A' at 0x00000000037E5E58>
      • root.find('孩子A/子孫C')
        • <Element '子孫C' at 0x00000000037E5EF8>
  • '//'
    • 該節點下的所有後代,需搭配節點名字
    • 例子
      • root.find('.//孩子A')
        • <Element '孩子A' at 0x00000000037E5E58>
      • root.find('.//子孫C')
        • <Element '子孫C' at 0x00000000037E5EF8>
  • '.'
    • 表示當前節點
    • 例子
      • root.find('.').tag
  • '..' 
    • 表示節點父代,注意:ET 不會記錄當前節點的父代
    • 例子
      • root.find('.//子孫D/..')
        • <Element '孩子B' at 0x00000000037E5F98>
      • root.find('孩子A').find('..')
        • None
  • '[@attrib]'
    • 節點的屬性,可指定值
    • 例子
      • root.findall('*[@姓名]') 
        • [<Element '孩子A' at 0x00000000037E5E58>, <Element '孩子B' at 0x00000000037E5F98>]
      • root.find('孩子A[@姓名="大頭王"]')
        • <Element '孩子A' at 0x00000000037E5E58>
  • [tag='text']
    • 指定 child 的文字
    • 例子
      • root.find('*/子孫D[目前地點="鄰居家"]')
        • <Element '子孫D' at 0x00000000037EB098> 
  • [position]
    • 指定位置,需大於 0,需指定節點名字,無法搭配 '*' 使用
    • 例子
      • root.findall('*/目前地點[1]')
        • [<Element '目前地點' at 0x00000000037E5EA8>, <Element '目前地點' at 0x00000000037EB048>]
      • root.find('孩子B[last()]')
        • <Element '孩子B' at 0x00000000037E5F98>

xml.etree.ElementTree Module

  • xml.etree.ElementTree.fromstring(text)
    • 載入 xml 的 string
  • xml.etree.ElementTree.iterparse(source, events=None)
    • 逐步載入 xml 的檔案
    • source
      • 可為檔名 或 FileObject
    • events
      • 種類
        • "start"
        • "end"
        • "start-ns" => ns : namespace
        • "end-ns"
      • None => 只回報 "end"
    count = 0
    for event, elem in ET.iterparse(sys.argv[2]):
        if event == 'end':
            if elem.tag == 'location' and elem.text == 'Zimbabwe':
                count += 1
        elem.clear() # discard the element
    
    print count
    
  • xml.etree.ElementTree.parse(source, parser=None)
    • 載入 xml 的檔案
    • source
      • 可為檔名 或 FileObject 
    • parser
      • 解析器
  • xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra)
    • 建立 subElement 
    • parent
      • 所屬父代
    • tag
      • 標籤名字
    • attrib
      • 標籤屬性
  • xml.etree.ElementTree.register_namespace(prefix, uri)
    • 註冊 namespace 用在輸出 xml,與 find 等功能無關

Element Objects

  • class xml.etree.ElementTree.Element(tag, attrib={}, **extra)
    • 參數
      • tag
        • 標籤名字
      • attrib
        • 標籤屬性
    • 屬性
      • tag
        • 標籤名字
      • text
        • 標籤中的文字
      • tail
        • 標籤後的文字
        • <a><b>1<c>2<d/>3</c></b>4</a>
        • b tail = 4
      • attrib
        • 標籤屬性
    • 方法
      • clear()
      • get(key, default=None)
        • 得到屬性的值
      • items()
        • 回傳全部屬性的 (名字, 值)
      • keys()
        • 回傳全部屬性的名字
      • set(key, value)
        • 設定屬性
      • append(subelement)
      • extend(subelements)
      • find(match, namespaces=None)
        • 尋找第一個符合的 tag
      • findall(match, namespaces=None)
        • 尋找全部符合的 tag
      • findtext(match, default=None, namespaces=None)
        • 尋找第一個符合的 tag,並回傳 text
      • insert(index, subelement)
      • iter(tag=None)
        • 逐步回傳指定的 tag
        • 例子
          • root.iter("子孫C")
      • iterfind(match, namespaces=None)
        • 逐步回傳符合的 tag
      • itertext()
        • 逐步回傳文字
      • remove(subelement)

ElementTree Objects

  • class xml.etree.ElementTree.ElementTree(element=None, file=None) 
    • 參數
      • element
        • 提供 root 建立 tree
      • file
        • 提供檔案建立 tree
    • 方法
      (find, findall,... iterfind, ...) 皆是以 root 為起點
      • _setroot(element)
      • find(match, namespaces=None)
      • findall(match, namespaces=None)
      • findtext(match, default=None, namespaces=None)
      • getroot()
      • iter(tag=None)
      • iterfind(match, namespaces=None)
      • parse(source, parser=None)
      • write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml", *, short_empty_elements=True)

參考

用 ElementTree 在 Python 中解析 XML
Python爬蟲利器三之Xpath語法與lxml庫的用法
XPath Syntax

留言