องค์ประกอบต้นไม้ xml

ฉันไม่เข้าใจว่าทำไมฉันถึงได้รับข้อผิดพลาดขณะพยายามเข้าถึงการประทับเวลา รูปแบบ XML (ละแอตทริบิวต์บางส่วนออก):

แก้ไข: นี่คือประเภทที่แท้จริงของไฟล์ xml

<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
    <siteinfo>
        <sitename>Wikipedia</sitename>
        <dbname>enwiki</dbname>
        <base>https://en.wikipedia.org/wiki/Main_Page</base>
        <generator>MediaWiki 1.27.0-wmf.18</generator>
        <case>first-letter</case>
        <namespaces>...</namespaces>
    </siteinfo>
    <page>
        <title>Zhuangzi</title>
        <ns>0</ns>
        <id>42870472</id>
        <revision>
            <id>610251969</id>
            <timestamp>2014-05-26T20:08:14Z</timestamp>
            <contributor>
                <username>White whirlwind</username>
                <id>8761551</id>
            </contributor>
            <comment>...</comment>
            <model>wikitext</model>
            <format>text/x-wiki</format>
            <text xml:space="preserve" bytes="41">#REDIRECT [[Zhuang Zhou]] {{R from move}}</text>
            <sha1>9l31fcd4fp0cfxgearifr7jrs3240xl</sha1>
        </revision>
        <revision>...</revision>
        <revision>...</revision>
        <revision>...</revision>
        <revision>...</revision>
        <revision>...</revision>

    </page>
    <page>...</page>
</mediawiki>

แต่เมื่อฉันลองสิ่งต่อไปนี้:

for page in root:          
  for revision in page:
    print(revision.find('timestamp').text)

ฉันได้รับข้อผิดพลาด

   print(revision.find('timestamp').text)
   AttributeError: 'NoneType' object has no attribute 'text'

person Knokkelgeddon    schedule 31.03.2016    source แหล่งที่มา
comment
คุณบอกว่าคุณค้นหา 'timestamp' ในวัตถุ revision: revision.find('timestamp') แต่ข้อความแสดงข้อผิดพลาดแจ้งว่าคุณกำลังค้นหา 'revision' ใน revision: revision.find('revision') อันไหนจริง?   -  person CiaPan    schedule 31.03.2016
comment
`การประทับเวลา'' คือสิ่งที่ฉันกำลังมองหา   -  person Knokkelgeddon    schedule 31.03.2016


คำตอบ (2)


คุณกำลังวนซ้ำแต่ละแท็ก ดังนั้นการใช้ .find ในทุกแท็กจะส่งคืน None ดังนั้นข้อผิดพลาดของคุณ:

In [9]: for page in root:
            print(page.tag)
            for revision in page:
                  print(revision.tag)
   ...:         

id
timestamp
contributor
comment
model

โดยใช้วิธีการของคุณเอง คุณจะต้องตรวจสอบแต่ละแท็ก:

xml = fromstring(xml)

for page in xml:
    for revision in page:
      if revision.tag == "timestamp":
          print(revision.text)

คุณสามารถใช้ findall เพื่อรับแท็กการแก้ไขทั้งหมด จากนั้นแยกการประทับเวลา:

In [1]: xml = """<page>
   ...:    <title>Zhuangzi</title>
   ...:    <ns>0</ns>
   ...:    <id>42870472</id>
   ...:    <revision>
   ...:       <id>610251969</id>
   ...:       <timestamp>2014-05-26T20:08:14Z</timestamp>
   ...:       <contributor>
   ...:          <username>White whirlwind</username>
   ...:          <id>8761551</id>
   ...:       </contributor>
   ...:       <comment>TEXT</comment>
   ...:       <model>wikitext</model>
   ...:    </revision>
   ...: </page>"""

In [2]: import xml.etree.ElementTree as ET

In [3]: from StringIO import StringIO

In [4]: tree = ET.parse(StringIO(xml))

In [5]: root = tree.getroot()


In [6]: print([r.find("timestamp").text for r in root.findall("revision")])
['2014-05-26T20:08:14Z']

หากคุณใช้ lxml คุณสามารถใช้นิพจน์ xpath ธรรมดาได้:

from lxml.etree import parse,fromstring

xml = """<page>
   <title>Zhuangzi</title>
   <ns>0</ns>
   <id>42870472</id>
   <revision>
      <id>610251969</id>
      <timestamp>2014-05-26T20:08:14Z</timestamp>
      <contributor>
         <username>White whirlwind</username>
         <id>8761551</id>
      </contributor>
      <comment>TEXT</comment>
      <model>wikitext</model>
   </revision>
</page>"""


root = fromstring(xml)

print(root.xpath("//revision/timestamp/text()"))
['2014-05-26T20:08:14Z']

จากสิ่งที่คุณโพสต์ คุณต้องใช้การแมปเนมสเปซ:

tree = ET.parse("your_xml")
root = tree.getroot()
ns = {"wiki":"http://www.mediawiki.org/xml/export-0.10/"}


ts = [ts.text for ts in root.findall(".//wiki:revision//wiki:timestamp", ns) ]

สมมติว่าแท็กการแก้ไขทั้งหมดมีแท็กการประทับเวลา

หรือใช้ lxml กับ xpath:

from lxml.etree import parse


tree = parse("your_fie")
ns = {"wiki": "http://www.mediawiki.org/xml/export-0.10/"}

print(tree.xpath("//wiki:revision//wiki:timestamp//text()",namespaces=ns))

ถ้าคุณพิมพ์

tree = parse("test.xml")

for elem in tree.getiterator():
    print elem.tag

ผลลัพธ์คือ:

{http://www.mediawiki.org/xml/export-0.10/}mediawiki
{http://www.mediawiki.org/xml/export-0.10/}siteinfo
{http://www.mediawiki.org/xml/export-0.10/}sitename
{http://www.mediawiki.org/xml/export-0.10/}dbname
{http://www.mediawiki.org/xml/export-0.10/}base
{http://www.mediawiki.org/xml/export-0.10/}generator
{http://www.mediawiki.org/xml/export-0.10/}case
{http://www.mediawiki.org/xml/export-0.10/}namespaces
{http://www.mediawiki.org/xml/export-0.10/}page
.............................

.

person Padraic Cunningham    schedule 31.03.2016
comment
XPath ใช้งานได้กับ lxml แต่คำถามถูกแท็ก elementtree - person mzjn; 31.03.2016
comment
@mzjn ใช่อ่านแท็กผิด แต่ตรรกะและ findall ทำงานเหมือนกันทุกประการสำหรับ xml - person Padraic Cunningham; 31.03.2016
comment
print([r.find("timestamp").text for r in root.findall("revision")])" ไม่พิมพ์อะไรเลย ฉันมีเอกสารที่นำเข้าเป็น tree = ET.parse('2articles.xml') root = tree.getroot() - person Knokkelgeddon; 31.03.2016
comment
หากคุณสามารถแชร์ไฟล์ได้ ฉันจะแสดงวิธีรับสิ่งที่คุณต้องการ - person Padraic Cunningham; 31.03.2016

ฉันก็แค่ทำสิ่งที่ชอบ:

import xml.etree.ElementTree as ET
root = ET.parse('your_xml_file.xml')
timestamp = root.find('.//timestamp').text

หาก xml ของคุณมีองค์ประกอบการประทับเวลามากกว่าหนึ่งรายการ ฉันจะเปลี่ยนบรรทัดสุดท้ายด้วย:

timestamps = [t.text for t in root.findall('.//timestamp')]
person Giuseppe Cammarota    schedule 31.03.2016