φυβλαςのβλογ
phyblas的博客



[python] การจัดการ xml ด้วย elementtree
เขียนเมื่อ 2020/02/18 18:30
แก้ไขล่าสุด 2024/02/22 10:39

XML ย่อมาจาก Extensible Markup Language = "ภาษามาร์กอัปขยายได้" เป็นรูปแบบโครงสร้างการจัดเก็บข้อมูลชนิดหนึ่งที่นิยมใช้ ข้อมูล XML จะถูกเก็บในไฟล์สกุล .xml

ภาษา html ซึ่งนิยมใช้ในการเขียนเว็บนั้นก็แตกย่อยมาจาก xml แต่ xml นั้นใช้ในงานต่างๆอย่างกว้างขวาง ไม่ใช่แค่เขียนเว็บ

สำหรับการสกัดข้อมูล html นั้นนิยมใช้ beautifulsoup ซึ่งเป็นมอดูลเสริมที่ต้องทำการติดตั้งเพิ่มเติม (อ่านวิธีใช้ได้ใน https://phyblas.hinaboshi.com/20180323)

ส่วนการจัดการกับข้อมูล xml นั้นทางไพธอนได้เตรียมมอดูลเอาไว้แล้วในตัว ก็คือมอดูลชื่อ xml (ตรงไปตรงมาเลย)

ภายในมอดูลแบ่งเป็นหลายส่วน แต่วิธีที่เบื้องต้นที่ง่ายที่สุดคือวิธีการใช้ elementtree

elementtree จะช่วยทำให้เราสามารถดึงข้อมูลจาก xml มาจัดการหรือวิเคราะห์ หรือแม้แต่สร้างขึ้นมาใหม่ได้โดยง่าย

นอกจากนี้ยังมีมอดูล lxml ซึ่งเป็นมอดูลเสริมที่ต้องติดตั้งเพิ่มเอง ความสามารถโดยรวมใกล้เคียงจากมอดูล xml แต่เพิ่มความสามารถบางอย่างขึ้นมา แต่ในที่นี้จะยังไม่พูดถึง lxml จะใช้แค่ elementtree ในมอดูล xml ซึ่งมีอยู่ในไพธอนแต่แรก




เข้าใจโครงสร้างของ xml

ขอใช้โค้ดที่เขียนในรูป xml นี้เป็นตัวอย่าง ให้คัดลอกโค้ดนี้ไปบันทึกใส่ในไฟล์

ไฟล์ pdata.xml
<pdata>
  <trainer name="ซาโตชิ">
    <pokemon species="พีคาชู" lv="99">
      <skill name="ไฟฟ้าช็อต 220 โวลต์" pp="5" />
      <skill name="กระดิกหาง" pp="30" />
      <item name="บงงุริ" ea="1" />
      <type>
        ไฟฟ้า
      </type>
    </pokemon>
    <pokemon species="ฟุชิงิดาเนะ" lv="5">
      <skill name="แส้เถาวัลย์" pp="10" />
      <skill name="กระดิกหาง" pp="30" />
      <item name="บงงุริ" ea="2" />
      <type>
        พืช
      </type>
    </pokemon>
    <item name="มอนสเตอร์บอล" ea="5" />
    <item name="ศิลาไฟฟ้า" ea="1" />
  </trainer>
  <trainer>
    <pokemon species="เซนิงาเมะ" lv="12">
      <skill name="กระสุนน้ำ" pp="30" />
    </pokemon>
  </trainer>
</pdata>

ในที่นี้ขออธิบายโค้ดแบบคร่าวๆพอให้เข้าใจได้ สำหรับคนที่ยังไม่มีพื้นฐาน html หรือ xml

โครงสร้าง xml จะประกอบไปด้วยสิ่งที่เรียกว่า "แท็ก" (tag) ซึ่งก็คือส่วนที่ล้อมด้วย < >

ข้อความที่อยู่ซ้ายสุดภายในกรอง < > ก็คือชื่อแท็ก และอาจตามด้วยแอตทริบิวต์และค่าของแอตทริบิวต์นั้น หรืออาจไม่มีก็ได้

แท็กที่ไม่มีเครื่องหมาย / (แสลช) อยู่จะเรียกว่าเป็นแท็กเปิด ส่วนที่ขึ้นต้นด้วย / คือแท็กปิด เมื่อมีแท็กเปิดก็ต้องมีแท็กปิดที่มีชื่อเหมือนกัน ต้องมีคู่เสมอ เช่นแท็ก type ประกอบไปด้วยแท็กเปิด <type> และแท็กปิด </type>

ในระหว่างแท็กเปิดกับแท็กปิดจะแทรกด้วยโครงสร้างที่อยู่ลึกเข้าไปชั้นในต่อไป ด้านในอาจจะใส่แท็กอื่นหรือใส่ข้อความก็ได้ แท็กที่อยู่ด้านในแท็กอื่นจะเรียกว่าแท็กลูก (child) และแท็กที่มีแท็กลูกนั้นอยู่จะเรียกว่าเป็นแท็กพ่อแม่ (parent) ของแท็กนั้น ส่วนแท็กที่อยู่ชั้นนอกสุดจะเรียกว่าเป็นราก (root)

ในตัวอย่างนี้แท็กที่เป็นราก (แท็กชั้นนอกสุด) คือ pdata และลึกเข้ามามีแท็ก trainer อยู่ ๒ อัน โดยแท็ก trainer อันแรกมีแอตทริบิวต์ name ติดอยู่ด้วย

นอกจากนี้ยังมีแท็กที่มี / อยู่ทางขวาสุด แท็กประเภทนี้คือแท็กที่อยู่เดี่ยวๆ เป็นทั้งแท็กเปิดและปิดไปในตัว ไม่ต้องมีคู่ เช่นแท็ก skill และแท็ก item ในที่นี้

ใน xml ขอแค่ยึดหลักการเขียนโครงสร้างตามนี้จะสร้างแท็กชื่ออะไร ในแท็บมีพรอเพอร์ตีชื่ออะไรก็ได้ กำหนดได้อิสระ ขึ้นอยู่กับว่าจะเอาไปใช้งานทำอะไร เช่นถ้าเป็น html แต่ละแท็กก็จะมีความหมายเป็นโครงสร้างส่วนต่างๆของเว็บไซต์

สำหรับโค้ด xml ข้างต้นนี้เป็นแค่โค้ดที่สร้างสมมุติขึ้นมาเพื่อเป็นตัวอย่าง ไม่ได้ถูกนำไปใช้จริงที่ไหน ไม่ได้มีความหมายอะไรเป็นพิเศษ แต่รูปแบบที่เขียนมีลักษณะเป็นโครงสร้างตามหลัก xml




การอ่าน xml เข้ามาใน elementtree

ต่อไปจะใช้ไพธอนเพื่อทำการอ่านข้อมูล xml ในตัวอย่างข้างต้นนี้เข้ามา แล้วแปลงให้อยู่ในรูปของ elementtree

elementtree ในไพธอนเป็นออบเจ็กต์ชนิดหนึ่งซึ่งแทนตัวเก็บข้อมูล xml การจัดการข้อมูล xml ในรูปของ elementtree สามารถทำได้ง่าย

elementtree เป็นมอดูลย่อยของมอดูล xml อยู่ใน xml.etree.ElementTree

การอ่านโค้ด xml ขึ้นมาจากไฟล์ทำได้โดยใช้ฟังก์ชัน parse แล้วจะได้ออบเจ็กต์ ElementTree ซึ่งเก็บข้อมูลในไฟล์นั้น จากนั้นใช้เมธอด .getroot() ในออบเจ็กต์นั้นก็จะได้ออบเจ็กต์ของแท็กรากของข้อมูลนี้ เรียกว่าเป็นองค์ประกอบ (element)
import xml.etree.ElementTree as et

xmlpdata = et.parse('pdata.xml')
print(xmlpdata) # ได้ <xml.etree.ElementTree.ElementTree object at 0x105155b50>
roottag = xmlpdata.getroot()
print(roottag) # ได้ <Element 'pdata' at 0x105150650>

ในบทความนี้จะย่อ ElementTree เป็น et ทั้งหมด จากนี้ต่อไปก็ด้วย

หากต้องการดูเนื้อในของแท็กก็อาจใช้ฟังก์ชัน et.tostring
print(et.tostring(roottag,encoding='unicode'))

ได้
<pdata>
  <trainer name="ซาโตชิ">
    <pokemon lv="99" species="พีคาชู">
      <skill name="ไฟฟ้าช็อต 220 โวลต์" pp="5" />
      <skill name="กระดิกหาง" pp="30" />
      <item ea="1" name="บงงุริ" />
      <type>
        ไฟฟ้า
      </type>
    </pokemon>
    <pokemon lv="5" species="ฟุชิงิดาเนะ">
      <skill name="แส้เถาวัลย์" pp="10" />
      <skill name="กระดิกหาง" pp="30" />
      <item ea="2" name="บงงุริ" />
      <type>
        พืช
      </type>
    </pokemon>
    <item ea="5" name="มอนสเตอร์บอล" />
    <item ea="1" name="ศิลาไฟฟ้า" />
  </trainer>
  <trainer>
    <pokemon lv="12" species="เซนิงาเมะ">
      <skill name="กระสุนน้ำ" pp="30" />
    </pokemon>
  </trainer>
</pdata>

ในที่นี้ encoding='unicode' ใส่ไว้เพื่อให้ตัวอักษรที่ไม่ใช่ ASCII เช่นอักษรไทย สามารถถูกบันทึกได้ถูกต้อง ไม่เช่นนั้นจะกลายเป็นโค้ด

ผลที่ได้จะเห็นว่าได้เป็นโค้ด xml ตามไฟล์ที่เปิดมา แต่ว่าไม่ได้เหมือนกับข้อความในไฟล์ต้นฉบับเดิมเสียทีเดียว แต่มีการจัดใหม่ มีการเรียงแอตทริบิวต์ของแท็กใหม่ เนื่องจากแอตทริบิวต์เมื่อถูกอ่านเข้ามาใน elementtree จะไม่มีลำดับ แต่เมื่อแปลงกลับเป็นโค้ดจะมีการเรียงแอตทริบิวต์ตามตัวอักษร

วิธีการอ่านไฟล์อาจเขียนได้อีกแบบคือโดยสร้างออบเจ็กต์ ElementTree ขึ้นมาโดยตรง โดยใส่คีย์ file=ชื่อไฟล์
xmlpdata = et.ElementTree(file='pdata.xml')
roottag = xmlpdata.getroot()
print(roottag) # ได้ <Element 'pdata' at 0x105178a10>




การดูข้อมูลและองค์ประกอบภายในแท็ก

ชื่อของแท็กสามารถดูได้ที่ .tag และดูแอตทริบิวต์ได้ที่ .atrrib
print(roottag.tag) # ได้ pdata
print(roottag.attrib) # ได้ {}

แอตทริบิวต์ที่มีจะแสดงผลในรูปดิกชันนารี ในที่นี้แท็ก pdata ไม่มีแอตทริบิวต์ใดๆ จึงออกมาเป็นดิกชันนารีเปล่า

ออบเจ็กต์ element นี้มีคุณสมบัติเป็นลิสต์ โดยที่แท็กลูกที่อยู่ภายในแท็กนี้ก็จะเป็นสมาชิกในลิสต์

ในที่นี้ pdata ซึ่งเป็นแท็กรากมีองค์ประกอบอยู่ ๒ ตัวคือแท็ก trainer ทั้ง ๒ อัน ลองเข้าถึงแท็กภายในนั้นดูได้แบบเดียวกับลิสต์
print(len(roottag)) # ได้ 2
satoshi = roottag[0]
print(satoshi.tag) # ได้ trainer
print(satoshi.attrib) # ได้ {'name': 'ซาโตชิ'}
trainerA = roottag[1] 
print(trainerA.tag) # ได้ trainer

หรือจะใช้ for เพื่อทำการวนซ้ำก็ได้
s = ''
for tag in roottag:
    s += tag.tag+'; '
print(s) # ได้ trainer; trainer; 

การเอาแท็กมาวน for โดยทั่วไปจะวนแค่แท็กลูกที่อยู่ในแท็กนั้นโดยตรงเท่านั้น

อาจใช้เมธอด .iter() เพื่อให้ใช้ for แล้ววนเอาแท็กลูกทั้งที่อยู่ในนั้นโดยตรงหรือที่อยู่ในขั้นลึกลงไป
s = ''
for tag in roottag.iter():
    s += tag.tag+'; '
print(s) # ได้ pdata; trainer; pokemon; skill; skill; item; type; pokemon; skill; skill; item; type; item; item; trainer; pokemon; skill; 

การเอาค่าแอตทริบิวต์ของแท็กออกมาอาจใช้เมธอด .get(ชื่อแอตทริบิวต์) หรือจะเอาค่าจากดิกชันนารีในจุด .attrib ก็ได้
print(satoshi.attrib['name']) # ได้ ซาโตชิ
print(satoshi.get('name')) # ได้ ซาโตชิ

และยังมีเมธอด .keys() สำหรับเอาชื่อของแอตทริบิวต์ทั้งหมด และเมธอด .items() สำหรับเอาคู่ของชื่อและค่าออกมาในรูปของลิสต์ของทูเพิล
print(satoshi.keys()) # ได้ ['name']
print(satoshi.items()) # ได้ [('name', 'ซาโตชิ')]

แท็ก trainer ซึ่งเป็นแท็กลูกที่ได้มานี้ก็เป็นออบเจ็กต์ element เช่นเดียวกัน สามารถดูข้อมูลที่ย่อยอยู่ภายในชั้นต่อๆไปได้อีก
print(len(satoshi)) # ได้ 4

pikachu = satoshi[0]
print(pikachu.tag) # ได้ 
print(pikachu.attrib) # ได้ pokemon
print(len(pikachu)) # ได้ 4 {'species': 'พีคาชู', 'lv': '99'}

fushigidane = satoshi[1]
print(fushigidane.tag) # ได้ pokemon
print(fushigidane.attrib) # ได้{'species': 'ฟุชิงิดาเนะ', 'lv': '5'}
print(len(fushigidane)) # ได้ 4

msball = satoshi[2]
print(msball.tag) # ได้ item
print(msball.attrib) # ได้ {'name': 'มอนสเตอร์บอล', 'ea': '5'}
print(len(msball)) # ได้ 0

ในที่นี้แท็ก item เป็นแท็กที่เปิดและปิดในตัว ไม่มีอะไรอยู่ข้างใน จึงเป็นลิสต์เปล่า

แท็ก type ในที่นี้ไม่มีแท็กอยู่ข้างใน และจะเห็นว่ามีข้อความที่ไม่ใช่แท็กอยู่ ข้อความส่วนนี้จะอยู่ที่ .text
typetag = pikachu[3]
print(typetag.tag) # ได้ type
print(len(typetag)) # ได้ 0
print(typetag.text) # ได้ ไฟฟ้า




การค้นหาแท็กลูกตามชื่อ

แท็กมีเมธอด .find() และ .findall() เอาไว้ค้นหาแท็กลูกภายในโดยดูจากชื่อแท็ก

.find() จะเอาแค่ตัวแรกที่เจอ ส่วน .findall() ค้นทั้งหมดแล่้วให้ลิสต์ของแท็กที่หามาได้
import xml.etree.ElementTree as et

xmlpdata = et.parse('pdata.xml')
roottag = xmlpdata.getroot()

print(roottag.find('trainer')) # ได้ <Element 'trainer' at 0x1189c8f50>
print(roottag.findall('trainer')) # ได้ [<Element 'trainer' at 0x1189c8f50>, <Element 'trainer' at 0x1189acd10>]

นอกจากนี้ยังมีเมธอด .iterfind() จะค้นทั้งหมดเหมือนกับ .findall() แต่จะได้มาในรูปของอิเทอเรเตอร์ เอาไว้ใช้วนใน for
trainer = roottag.iterfind('trainer')
print([(tr.tag,tr.attrib) for tr in trainer])
# ได้ [('trainer', {'name': 'ซาโตชิ'}), ('trainer', {})]

แม้ว่าจริงๆแล้วใช้ .findall() ก็ได้มาเป็นลิสต์แล้วก็สามารถวนใน for ได้เช่นกันก็ตาม แต่ถ้าต้องการใช้กับ for อยู่แล้วโดยไม่ได้ต้องการเอาลิสต์ของแท็กทั้งหมดในทันทีก็ใช้ .iterfind() จะดีกว่า

แต่แท็กจะถูกค้นแค่เฉพาะที่เป็นแท็กลูกของแท็กนั้นโดยตรงเท่านั้น จะไม่ได้ค้นแท็กที่อยู่ลึกลงไป เช่นในที่นี้แท็ก item อยู่มีอยู่ในแท็ก trainer และก็มีอยู่ในแท็ก pokemon ด้วย ต้องค้นที่แท็กนั้นโดยตรงจึงเจอ
satoshi = roottag.find('trainer')
item = satoshi.iterfind('item')
print([x.get('name') for x in item]) # ได้ ['มอนสเตอร์บอล', 'ศิลาไฟฟ้า']

pikachu = satoshi.find('pokemon')
item = pikachu.iterfind('item')
print([x.get('name') for x in item]) # ได้ ['บงงุริ']

หากต้องการค้นทั้งหมดแม้แต่ระดับที่ลึกลงไปก็ให้เติม .// ไปด้านหน้า
item = roottag.iterfind('.//item')
print([x.get('name') for x in item]) # ได้ ['บงงุริ', 'บงงุริ', 'มอนสเตอร์บอล', 'ศิลาไฟฟ้า']

แบบนี้จะเห็นว่าค้นที่ตัวแท็กราก แต่ว่าเจอแท็กชื่อ item ที่อยู่ด้านในทั้งหมดไม่ว่าจะอยู่ลึกลงไปแค่ไหน

ถ้าเติม * จะหมายถึงค้นแท็กชื่ออะไรก็ได้ และถ้าใช้คู่กับ .// จะเป็นการค้นแท็กทั้งหมดรวมที่อยู่ในชั้นที่ลึกเข้าไป
taga = roottag.iterfind('*')
print([x.tag for x in taga]) # ได้ ['trainer', 'trainer']
taga = roottag.iterfind('.//*')
print([x.tag for x in taga]) # ได้ ['trainer', 'pokemon', 'skill', 'skill', 'item', 'type', 'pokemon', 'skill', 'skill', 'item', 'type', 'item', 'item', 'trainer', 'pokemon', 'skill']

ถ้าต้องการหาแท็กที่มีค่าของแอตทริบิวต์เป็นไปตามที่ต้องการเท่านั้นก็ทำได้โดยเขียน [@ชื่อแอตทริบิวต์] เช่น
taga = roottag.iterfind('.//*[@name]')
print([x.tag for x in taga])
# ได้ ['trainer', 'skill', 'skill', 'item', 'skill', 'skill', 'item', 'item', 'item', 'skill']

taga = roottag.iterfind('.//*[@species]')
print([(x.tag,x.get('species')) for x in taga])
# ได้ [('pokemon', 'พีคาชู'), ('pokemon', 'ฟุชิงิดาเนะ'), ('pokemon', 'เซนิงาเมะ')]

ถ้าต้องการกำหนดค่าของแอตทริบิวต์ที่จะเอาก็เขียน [@ชื่อแอตทริบิวต์=ค่า] เช่น
taga = roottag.iterfind('.//*[@ea="1"]')
print([(x.tag,x.attrib) for x in taga])
# ได้ [('item', {'name': 'บงงุริ', 'ea': '1'}), ('item', {'name': 'ศิลาไฟฟ้า', 'ea': '1'})]

หาแท็กที่มีแท็กลูกตามที่ต้องการได้โดยเขียน [ชื่อแท็กลูก] เช่น
taga = roottag.iterfind('*[pokemon]')
print([(x.tag,x.attrib) for x in taga])
# ได้ [('trainer', {'name': 'ซาโตชิ'}), ('trainer', {})]

taga = roottag.iterfind('*[item]')
print([(x.tag,x.attrib) for x in taga])
# ได้ [('trainer', {'name': 'ซาโตชิ'})]

taga = roottag.iterfind('.//*[item]')
print([(x.tag,x.attrib) for x in taga])
# ได้ [('trainer', {'name': 'ซาโตชิ'}), ('pokemon', {'species': 'พีคาชู', 'lv': '99'}), ('pokemon', {'species': 'ฟุชิงิดาเนะ', 'lv': '5'})]




การสร้าง elementtree และบันทึกเป็น xml

นอกจากจะเปิดไฟล์ .xml ที่มีอยู่แล้วมาเป็น elementtree ได้ ในทางกลับกันเราสามารถสร้างแท็กขึ้นมา

ออบเจ็กต์แท็กคือ et.Element สามารถสร้างขึ้นมาได้โดยใส่ชื่อแท็ก ตามด้วยแอตทริบิวต์ที่ต้องการ
kusaihana = et.Element('pokemon',species='คุไซฮานะ',lv=22)
print(kusaihana) # ได้ <Element 'pokemon' at 0x10512b230>
print(kusaihana.tag) # ได้ pokemon
print(kusaihana.attrib) # ได้ {'species': 'คุไซฮานะ', 'lv': 22}


หรืออาจใช้ฟังก์ชัน et.fromstring เพื่อสร้างจากสายอักขระเปล่าๆได้
hitokage = et.fromstring('<pokemon species="ฮิโตคาเงะ" lv="11"><skill name="พ่นไฟ" /></pokemon>')

สามารถเอาแท็กมาใส่ในออบเจ็กต์ et.ElementTree แล้วนำมาบันทึกลงไฟล์ได้โดยใช้เมธอด .write()
hitokage_et = et.ElementTree(hitokage)
hitokage_et.write('hitokage.xml',encoding='unicode')

ได้ไฟล์ hitokage.xml
<pokemon lv="11" species="ฮิโตคาเงะ"><skill name="พ่นไฟ" /></pokemon>




การแก้ xml ใน elementtree

ออบเจ็กต์ et.Element นั้นมีเมธอดต่างๆที่ช่วยให้เพิ่มและลบหรือแก้ข้อมูลภายในแท็กได้โดยง่าย

การเพิ่มแอตทริบิวต์ลงไปทำได้โดยเมธอด .set() หรือแก้ค่าที่มีอยู่แล้วก็ได้
item = et.Element('item')
item.set('name','หน้ากากอนามัย')
print(et.tostring(item,encoding='unicode')) # ได้ <item name="หน้ากากอนามัย" />
item.set('lv','10')
print(et.tostring(item,encoding='unicode')) # ได้ <item lv="10" name="หน้ากากอนามัย" />
item.set('lv','95')
print(et.tostring(item,encoding='unicode')) # ได้ <item lv="95" name="หน้ากากอนามัย" />

การเพิ่มแท็กลูกลงไปด้านในสามารถทำได้โดยเมธอด .append()
vr = et.Element('vr',name='covid')
item.append(vr)
print(et.tostring(item,encoding='unicode'))
# ได้ <item lv="95" name="หน้ากากอนามัย"><virus name="covid" /></item>

จะเห็นว่าเดิมทีแท็กที่ไม่มีแท็กลูกภายในจะเป็นแท็กที่เปิดปิดในตัว คือมี / อยู่ท้าย แต่เมื่อแทรกแท็กเข้าไปข้างในจะมีการแยกเป็นแท็กเปิดแท็กปิด โดยมีแท็กที่แทรกไว้ข้างในอยู่

หรืออาจใช้ฟังก์ชัน et.SubElement()
et.SubElement(item,'pm',lv='10')
print(et.tostring(item,encoding='unicode'))
# ได้ <item lv="95" name="หน้ากากอนามัย"><vr name="covid" /><pm lv="10" /></item>

ถ้ามีแท็กลูกอยู่แล้ว พอใส่เพิ่มไปอีกจะไปต่อท้าย แต่ถ้าหากต้องการแทรกไปในตำแหน่งที่กำหนดให้ใช้เมธอด .insert() แล้วใส่ตำแหน่งที่ต้องการ
pm = et.Element('pm',lv='2.5')
item.insert(0,pm)
print(et.tostring(item,encoding='unicode'))
# ได้ <item lv="95" name="หน้ากากอนามัย"><pm lv="2.5" /><vr name="covid" /><pm lv="10" /></item>

การลบแท็กออกทำได้โดยใช้เมธอด .remove()
item.remove(item[1])
print(et.tostring(item,encoding='unicode'))
# ได้ <item lv="95" name="หน้ากากอนามัย"><pm lv="2.5" /><pm lv="10" /></item>

สิ่งที่ต้องใส่ใน .remove() ก็คือตัวออบเจ็กต์ของตัวแท็กลูกที่ต้องการเอาออก อาจใช้ .find หรือ .findall เพื่อหาตัวที่ต้องการลบจากชื่อที่ต้องการได้
item.remove(item.find('pm'))
print(et.tostring(item,encoding='unicode'))
# ได้ <item lv="95" name="หน้ากากอนามัย"><pm lv="10" /></item>

ถ้าจะลบออกทั้งหมดทั้งแท็กลูกทั้งแอตทริบิวต์อาจใช้เมธอด .clear()
item.clear()
print(et.tostring(item,encoding='unicode')) # ได้ <item />

หากต้องการเพิ่มแท็กไปทีเดียวหลายตัวก็ใช้เมธอด .extend() โดยใส่ลิสต์ของแท็กลูกที่ต้องการใส่เข้าไป
pmpm = [et.Element('pm',lv=x) for x in ['2.5','10','84000']]
item.extend(pmpm)
print(et.tostring(item,encoding='unicode'))
# ได้ <item><pm lv="2.5" /><pm lv="10" /><pm lv="84000" /></item>




สรุปเมธอดและแอตทริบิวต์

เมธอดและแอตทริบิวต์ของออบเจ็กต์ Element (ออบเจ็กต์แท็ก)

.tag ดูชื่อแท็ก
.atrrib ดูดิกชันนารีของแอตทริบิวต์ของแท็ก
.text ดูข้อความภายในแท็กที่ไม่ได้อยู่ในแท็กลูก
.get(ชื่อแอตทริบิวต์) หาค่าของแอตทริบิวต์ที่ต้องการ
item() ทำลิสต์ของทูเพิลของชื่อและค่าของแอตทริบิวต์ทั้งหมด
.key() ทำลิสต์ของชื่อแอตทริบิวต์ทั้งหมด
.iter() ทำอิเทอเรเตอร์ไล่แท็กทั้งหมดที่มีในนี้
.find(คำค้น) ค้นหาแท็กที่ต้องการ เอาตัวแรกที่เจอ
.findall(คำค้น) ค้นหาแท็กที่ต้องการ เอาทั้งหมดที่เจอ
.iterfind(คำค้น) ค้นหาแท็กที่ต้องการ ได้เป็นอิเทอเรเตอร์ไล่ออกมาทุกวัน
.append(แท็กลูก) เพิ่มแท็กลูกลงไปในตำแหน่งท้ายสุด
.insert(ตำแหน่ง, แท็กลูก) เพิ่มแท็กลูกลงไปในตำแหน่งที่ต้องการ
.extend(ลิสต์ของแท็กลูก) เพิ่มแท็กลูกลงไปพร้อมกันทีเดียวหลายอัน
.set(ชื่อแอตทริบิวต์, ค่า) ตั้งค่าให้แอตทริบิวต์ที่ต้องการ
.remove(แท็กลูก) ลบแท็กลูกที่ต้องการออก
.clear() ลบแท็กลูกและแอตทริบิวต์ทั้งหมดของแท็กนั้นออก




สรุปฟังก์ชันและคลาสใน elementtree

ในที่นี้ย่อ xml.etree.ElementTree เป็น et

et.parse(ชื่อไฟล์) สร้างออบเจ็กต์ elementtree ขึ้นมาจากไฟล์
et.ElementTree(แท็ก) สร้างออบเจ็กต์ elementtree จากแท็ก
et.ElementTree(file=ชื่อไฟล์) สร้างออบเจ็กต์ elementtree ขึ้นมาจากไฟล์
et.fromstring(โค้ด xml) สร้างออบเจ็กต์แท็กขึ้นมาจากสายอักขระที่เป็นโค้ด xml
et.Element(ชื่อแท็ก, แอตทริบิวต์=, ...) สร้างออบเจ็กต์แท็กตามชื่อแท็กและแอตทริบิวต์ที่กำหนด
et.SubElement(แท็กพ่อแม่, ชื่อแท็ก, แอตทริบิวต์=, ...) สร้างออบเจ็กต์แท็กตามชื่อแท็กและแอตทริบิวต์ที่กำหนด แล้วยัดใส่ให้แท็กพ่อแม่
et.tostring(แท็ก) แปลงแท็กเป็นสายอักขระของโค้ด xml




-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

目录

从日本来的名言
模块
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
机器学习
-- 神经网络
javascript
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  查看日志

  推荐日志

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ