Mundarija (23)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. XML tuzilishi
- 2.2. O'qish va navigatsiya
- 2.3. XPath qism to'plami
- 2.4. text va tail
- 2.5. Daraxt qurish va yozish
- 2.6. Nom fazolari (namespaces)
- 2.7. XML xavfsizligi
- 2.8. Oqimli tahlil (iterparse)
- 2.9. Xatolar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — O'qish, navigatsiya va XPath
- Misol 2 — Daraxt qurish va nom fazolari
- Misol 3 — Xavfsizlik va oqimli tahlil
- Misol 4 — Amaliy: RSS lentani o'qib qayta ishlash
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
16.5-dars: XML
16-QISM — MA'LUMOT FORMATLARI · 5-dars
1. Kirish va motivatsiya
XML — "kengaytiriladigan belgilash tili". JSON keng tarqalguncha u ma'lumot almashishning asosiy formati edi va bugun ham ko'p joyda yashaydi: RSS/Atom lentalar, SOAP veb-xizmatlar, Office hujjatlari (.docx, .xlsx — ichida XML), Android va Java sozlamalari, SVG, sitemap, bank va davlat integratsiyalari. XML ni o'qiy va yoza bilish — real integratsiya ishida zarur ko'nikma.
Real vaziyat. Bir jamoa hamkor bankdan kunlik tranzaksiya faylini XML ko'rinishida qabul qilardi. Boshida hammasi oddiy ko'rindi — xml.etree.ElementTree bilan o'qildi. Keyin uch muammo ketma-ket chiqdi. Birinchisi: fayl <Document xmlns="urn:iso:std:iso:20022..."> bilan boshlanardi — nom fazosi (namespace), va root.find("Tranzaksiya") hech narsa topmadi, chunki teg aslida {urn:iso...}Tranzaksiya edi. Ikkinchisi: fayl kattalashib 500 MB ga yetdi va ET.parse butun daraxtni xotiraga yuklab, serverni cho'ktirdi. Uchinchisi — eng jiddiysi: xavfsizlik auditi "billion laughs" hujumini ko'rsatdi — bir necha qatorli XML minglab marta kengayib, xotirani portlatishi mumkin edi.
Bu darsda XML ni ElementTree bilan o'qish va yozishni, nom fazolarini, oqimli tahlilni va — eng muhimi — XML ga xos xavfsizlik xatarlarini o'rganamiz.
Bu darsda:
-
fromstring/parse,find/findall/findtext, XPath qism to'plami - Atributlar,
textvatail - Daraxt qurish:
Element,SubElement,tostring,indent - Nom fazolari —
{uri}tegvaregister_namespace - Xavfsizlik: entity kengayishi ("billion laughs"), XXE
- Oqimli tahlil:
iterparse+elem.clear() ParseErrorva belgi ekranlash- Amaliy: RSS lentani o'qib qayta ishlash
2. Nazariya — chuqur tushuntirish
2.1. XML tuzilishi
<?xml version="1.0" encoding="UTF-8"?>
<katalog>
<kitob id="1" til="uz">
<nom>Oʻtkan kunlar</nom>
<narx valyuta="UZS">45000</narx>
</kitob>
</katalog>| Tushuncha | Misol |
|---|---|
| Element (teg) | <kitob>...</kitob> |
| Atribut | id="1" |
Matn (text) |
<nom> ichidagi Oʻtkan kunlar |
| Ildiz element | <katalog> |
| Ichma-ichlik | kitob → nom, narx |
JSON dan farqi: XML da atribut va element farqi bor, matn va bolalar aralashishi mumkin, tartib saqlanadi, turlar yo'q (hammasi matn).
2.2. O'qish va navigatsiya
| Funksiya | Nima qiladi |
|---|---|
ET.fromstring(matn) |
Satrdan → ildiz Element |
ET.parse(fayl) |
Fayldan → ElementTree (.getroot()) |
elem.find(yol) |
Birinchi mos element (yoki None) |
elem.findall(yol) |
Barcha mos elementlar ro'yxati |
elem.findtext(yol) |
Mos elementning matni |
elem.iterfind(yol) |
Iterator (katta daraxt uchun) |
elem.get("atr") |
Atribut qiymati (yoki None) |
Element — ro'yxatga o'xshaydi: len(elem) — bolalar soni, for bola in elem, elem[0].
2.3. XPath qism to'plami
ElementTree XPath ning kichik qismini qo'llaydi:
| Ifoda | Ma'nosi |
|---|---|
nom |
Bevosita nom bolalari |
.//nom |
Istalgan chuqurlikdagi nom |
kitob/nom |
kitob ichidagi nom |
kitob[@id='2'] |
id atributi 2 bo'lgan kitob |
kitob[narx] |
narx bolasi bor kitob |
* |
Har qanday bola |
[1] |
Birinchi ( 1 dan, XPath odati) |
To'liq XPath emas: //, funksiyalar, o'qlar (ancestor::) yo'q — kerak bo'lsa lxml.
2.4. text va tail
<a>matn<b/>quyruq</a>| Atribut | Qiymati |
|---|---|
a.text |
"matn" |
b.tail |
"quyruq" — b dan keyingi matn |
Aralash kontent (matn + elementlar) da tail ni unutish — matnni yo'qotishning keng tarqalgan sababi.
2.5. Daraxt qurish va yozish
ildiz = ET.Element("katalog")
kitob = ET.SubElement(ildiz, "kitob", id="1")
ET.SubElement(kitob, "nom").text = "Sarob"
ET.indent(ildiz) # chiroyli otstup (3.9+)
matn = ET.tostring(ildiz, encoding="unicode") # str; encoding="utf-8" → bytes| Funksiya | Izoh |
|---|---|
ET.Element(teg, atr=...) |
Yangi element |
ET.SubElement(ota, teg) |
Bola qo'shadi va qaytaradi |
elem.set("atr", qiymat) |
Atribut o'rnatadi |
elem.append(bola) |
Element qo'shadi |
ET.indent(elem) |
Bo'shliq bilan formatlaydi |
ET.tostring(elem, encoding=...) |
Serializatsiya ("unicode" → str, aks holda bytes) |
ET.ElementTree(elem).write(fayl, ...) |
Faylga; xml_declaration=True |
<, >, &, " belgilar avtomatik ekranlanadi (< va h.k.) — ularni qo'lda almashtirmang.
2.6. Nom fazolari (namespaces)
<r xmlns="http://ex.uz/ns" xmlns:m="http://ex.uz/meta">
<a m:id="7">x</a>
</r>ElementTree nom fazosini teg nomiga {uri}teg ko'rinishida qo'shadi:
| Ko'rinish | Qiymati |
|---|---|
r.tag |
{http://ex.uz/ns}r |
| Qidirish | r.find("{http://ex.uz/ns}a") |
| NS li atribut | a.get("{http://ex.uz/meta}id") |
Amaliy usul — nom fazolarini lug'atga olib, find ga namespaces= berish:
NS = {"": "http://ex.uz/ns", "m": "http://ex.uz/meta"}
r.find("a", NS) # bo'sh prefiks ham ishlaydi (3.8+)Yozishda ET.register_namespace(prefiks, uri) — chiqishda chiroyli prefiks uchun.
2.7. XML xavfsizligi
XML ma'lumotni emas, hujjatni tasvirlaydi — va DTD (hujjat ta'rifi) orqali entity (belgilangan qisqartma) larni qo'llaydi. Bu ikki hujum turini keltirib chiqaradi:
1. Entity kengayishi ("billion laughs" / eksponensial portlash). Bir-biriga havola qiluvchi entity lar eksponensial kengayadi: 10 qatorli XML gigabaytlab xotira talab qilishi mumkin.
<!ENTITY lol0 "lol">
<!ENTITY lol1 "&lol0;&lol0;"> <!-- har daraja ikki baravar -->2. XXE (XML External Entity). Tashqi entity fayl yoki URL ni o'qishga urinadi:
<!ENTITY x SYSTEM "file:///etc/passwd">Python 3.14 stdlib holati:
| Xatar | xml.etree.ElementTree |
|---|---|
| Tashqi umumiy entity (XXE, fayl o'qish) | Hal qilinmaydi — xavfsiz sukut |
| Tashqi DTD yuklash | Yuklanmaydi |
| Ichki entity kengayishi (billion laughs) | Kengayadi — DoS mumkin |
Xulosa: stdlib XXE dan himoyalangan, lekin entity kengayishidan emas. Ishonchsiz XML uchun — defusedxml kutubxonasi (barcha entity va DTD ni bloklaydi).
2.8. Oqimli tahlil (iterparse)
Katta fayllarni butun daraxtni yuklamasdan:
for hodisa, elem in ET.iterparse(fayl, events=("end",)):
if elem.tag == "yozuv":
ishlash(elem)
elem.clear() # ⭐ xotirani bo'shatish elem.clear() bo'lmasa daraxt baribir xotirada to'planadi. Bu — katta XML ni qayta ishlashning yagona to'g'ri yo'li.
2.9. Xatolar
| Xato | Sabab |
|---|---|
ParseError: mismatched tag |
Yopilmagan/noto'g'ri teg; line, column bor |
ParseError: not well-formed |
Noto'g'ri belgi |
find None qaytaradi |
Nom fazosi hisobga olinmagan |
3. Tez ma'lumotnoma
import xml.etree.ElementTree as ET
ildiz = ET.fromstring(matn) # yoki ET.parse(fayl).getroot()
for kitob in ildiz.findall(".//kitob[@til='uz']"):
print(kitob.get("id"), kitob.findtext("nom"))
NS = {"a": "http://ex.uz/ns"}
ildiz.find("a:element", NS)
yangi = ET.Element("root")
ET.SubElement(yangi, "item", id="1").text = "qiymat"
ET.indent(yangi)
matn = ET.tostring(yangi, encoding="unicode")
for _, elem in ET.iterparse(katta_fayl, events=("end",)): # oqimli
if elem.tag == "yozuv":
...; elem.clear()Qoidalar
nom fazosi bor: {uri}teg yoki namespaces=
katta fayl: iterparse + elem.clear()
ishonchsiz XML: defusedxml
belgilarni qo'lda ekranlamang
find None qaytarsa — avval nom fazosini tekshiring
tail ni unutmang (aralash kontent)4. Batafsil misollar
Misol 1 — O'qish, navigatsiya va XPath
"""fromstring; find/findall/findtext; atributlar; XPath: shart, indeks, atribut; text va tail; Element ro'yxatga o'xshashligi."""
import xml.etree.ElementTree as ET
XML = """<?xml version="1.0" encoding="UTF-8"?>
<katalog>
<kitob id="1" til="uz">
<nom>Oʻtkan kunlar</nom>
<muallif>Abdulla Qodiriy</muallif>
<narx valyuta="UZS">45000</narx>
</kitob>
<kitob id="2" til="uz">
<nom>Sarob</nom>
<muallif>Abdulla Qahhor</muallif>
<narx valyuta="UZS">38000</narx>
</kitob>
<kitob id="3" til="ru">
<nom>Voyna i mir</nom>
<muallif>Lev Tolstoy</muallif>
</kitob>
</katalog>"""
def main() -> None:
ildiz = ET.fromstring(XML)
print(f"=== 1. Ildiz ===")
print(f" teg: {ildiz.tag}, bolalar soni: {len(ildiz)}")
print("\n=== 2. Aylanish va atributlar ===")
for kitob in ildiz.findall("kitob"):
narx = kitob.findtext("narx", default="—")
valyuta = kitob.find("narx").get("valyuta") if kitob.find("narx") is not None else ""
print(f" #{kitob.get('id')} [{kitob.get('til')}] {kitob.findtext('nom'):18} {narx} {valyuta}")
print("\n=== 3. XPath ===")
print(f" barcha nomlar: {[e.text for e in ildiz.iterfind('.//nom')]}")
muallif2 = ildiz.find(".//kitob[@id='2']/muallif")
print(f" id=2 muallifi: {muallif2.text}")
print(f" narxi bor kitoblar: {[k.get('id') for k in ildiz.findall('.//kitob[narx]')]}")
uzbekcha = [k.findtext("nom") for k in ildiz.findall(".//kitob[@til='uz']")]
print(f" uzbekcha kitoblar: {uzbekcha}")
print(f" birinchi kitob nomi: {ildiz.find('kitob[1]/nom').text}")
print("\n=== 4. Yo'q qiymatlar ===")
ruscha = ildiz.find(".//kitob[@id='3']")
print(f" narx elementi: {ruscha.find('narx')}")
print(f" findtext sukut bilan: {ruscha.findtext('narx', default='narx korsatilmagan')}")
print("\n=== 5. text va tail (aralash kontent) ===")
aralash = ET.fromstring("<xat>Hurmatli <ism>Aziz</ism>, xush kelibsiz <b>Wisar</b> ga!</xat>")
print(f" text: {aralash.text!r}")
for bola in aralash:
print(f" <{bola.tag}> text={bola.text!r} tail={bola.tail!r}")
print(f" butun matn: {''.join(aralash.itertext())!r}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ildiz ===
teg: katalog, bolalar soni: 3
=== 2. Aylanish va atributlar ===
#1 [uz] Oʻtkan kunlar 45000 UZS
#2 [uz] Sarob 38000 UZS
#3 [ru] Voyna i mir —
=== 3. XPath ===
barcha nomlar: ['Oʻtkan kunlar', 'Sarob', 'Voyna i mir']
id=2 muallifi: Abdulla Qahhor
narxi bor kitoblar: ['1', '2']
uzbekcha kitoblar: ['Oʻtkan kunlar', 'Sarob']
birinchi kitob nomi: Oʻtkan kunlar
=== 4. Yo'q qiymatlar ===
narx elementi: None
findtext sukut bilan: narx korsatilmagan
=== 5. text va tail (aralash kontent) ===
text: 'Hurmatli '
<ism> text='Aziz' tail=', xush kelibsiz '
<b> text='Wisar' tail=' ga!'
butun matn: 'Hurmatli Aziz, xush kelibsiz Wisar ga!'Nima ko'rsatdi: 2.2, 2.3, 2.4-bo'limlar.
Misol 2 — Daraxt qurish va nom fazolari
"""Element/SubElement bilan qurish; set; belgi ekranlash; indent; tostring; nom fazolari {uri}teg; namespaces= lug'at; register_namespace."""
import xml.etree.ElementTree as ET
def main() -> None:
print("=== 1. Daraxt qurish ===")
katalog = ET.Element("katalog", versiya="1.0")
for id_, nom, narx in [(1, "Sarob", 38000), (2, "Kecha va kunduz", 42000)]:
kitob = ET.SubElement(katalog, "kitob", id=str(id_))
ET.SubElement(kitob, "nom").text = nom
ET.SubElement(kitob, "narx", valyuta="UZS").text = str(narx)
ET.indent(katalog, space=" ")
print(ET.tostring(katalog, encoding="unicode"))
print("=== 2. ⭐ Belgi ekranlash ===")
izoh = ET.Element("izoh")
izoh.text = "5 < 10 & \"tirnoq\" > belgilar"
izoh.set("shart", "a < b")
print(f" {ET.tostring(izoh, encoding='unicode')}")
qaytgan = ET.fromstring(ET.tostring(izoh, encoding="unicode"))
print(f" qaytib o'qilganda asl matn: {qaytgan.text!r}")
print("\n=== 3. ⚠️ Nom fazolari — o'qish ===")
ns_xml = """<hujjat xmlns="urn:iso:20022" xmlns:b="urn:bank:meta">
<tranzaksiya b:id="TXN-7">
<summa>1500000</summa>
</tranzaksiya>
</hujjat>"""
ildiz = ET.fromstring(ns_xml)
print(f" ildiz.tag: {ildiz.tag}")
print(f" to'liq nom bilan: {ildiz.find('{urn:iso:20022}tranzaksiya') is not None}")
NS = {"": "urn:iso:20022", "b": "urn:bank:meta"}
tranzaksiya = ildiz.find("tranzaksiya", NS)
print(f" namespaces= lug'at bilan: summa={tranzaksiya.findtext('summa', namespaces=NS)}")
print(f" NS li atribut: {tranzaksiya.get('{urn:bank:meta}id')}")
print(f" find('tranzaksiya') NS siz: {ildiz.find('tranzaksiya')} ← None, chunki NS hisobga olinmadi")
print("\n=== 4. Nom fazosi bilan yozish ===")
ET.register_namespace("", "urn:iso:20022")
ET.register_namespace("b", "urn:bank:meta")
yangi = ET.Element("{urn:iso:20022}hujjat")
t = ET.SubElement(yangi, "{urn:iso:20022}tranzaksiya")
t.set("{urn:bank:meta}id", "TXN-9")
ET.SubElement(t, "{urn:iso:20022}summa").text = "2000000"
print(ET.tostring(yangi, encoding="unicode"))
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Daraxt qurish ===
<katalog versiya="1.0">
<kitob id="1">
<nom>Sarob</nom>
<narx valyuta="UZS">38000</narx>
</kitob>
<kitob id="2">
<nom>Kecha va kunduz</nom>
<narx valyuta="UZS">42000</narx>
</kitob>
</katalog>
=== 2. ⭐ Belgi ekranlash ===
<izoh shart="a < b">5 < 10 & "tirnoq" > belgilar</izoh>
qaytib o'qilganda asl matn: '5 < 10 & "tirnoq" > belgilar'
=== 3. ⚠️ Nom fazolari — o'qish ===
ildiz.tag: {urn:iso:20022}hujjat
to'liq nom bilan: True
namespaces= lug'at bilan: summa=1500000
NS li atribut: TXN-7
find('tranzaksiya') NS siz: None ← None, chunki NS hisobga olinmadi
=== 4. Nom fazosi bilan yozish ===
<hujjat xmlns="urn:iso:20022" xmlns:b="urn:bank:meta"><tranzaksiya b:id="TXN-9"><summa>2000000</summa></tranzaksiya></hujjat>Nima ko'rsatdi: 2.5, 2.6-bo'limlar.
Misol 3 — Xavfsizlik va oqimli tahlil
"""Entity kengayishi (billion laughs) eksponensial o'sadi; tashqi entity (XXE) stdlib da hal qilinmaydi; tashqi DTD yuklanmaydi; iterparse + clear bilan oqimli tahlil."""
import xml.etree.ElementTree as ET
def billion_laughs(daraja: int) -> str:
entitylar = "".join(f' <!ENTITY lol{i} "&lol{i - 1};&lol{i - 1};">\n' for i in range(1, daraja + 1))
return (f'<?xml version="1.0"?>\n<!DOCTYPE l [\n <!ENTITY lol0 "lol">\n'
f'{entitylar}]>\n<l>&lol{daraja};</l>')
def main() -> None:
print("=== 1. ⚠️ Entity kengayishi (billion laughs) ===")
for daraja in (4, 8, 12):
ildiz = ET.fromstring(billion_laughs(daraja))
print(f" daraja {daraja:2}: {len('lol')}×2^{daraja} = {len(ildiz.text):6} belgi (XML manba ~{daraja + 4} qator)")
print(" ⚠️ har daraja ikki baravar — 30-daraja gigabaytlarga yetadi (xotira DoS)")
print("\n=== 2. ✅ XXE — tashqi entity hal qilinmaydi ===")
xxe = ('<?xml version="1.0"?>\n<!DOCTYPE r [ <!ENTITY x SYSTEM "file:///maxfiy.txt"> ]>\n<r>&x;</r>')
try:
ET.fromstring(xxe)
except ET.ParseError as xato:
print(f" tashqi entity: {str(xato).split(':')[0]}")
print(" ⭐ fayl o'qilmadi — stdlib tashqi entity ni hal qilmaydi (XXE dan xavfsiz)")
print("\n=== 3. ✅ Tashqi DTD yuklanmaydi ===")
ext_dtd = '<?xml version="1.0"?>\n<!DOCTYPE r SYSTEM "http://mavjud-emas.invalid/x.dtd">\n<r>ok</r>'
print(f" tarmoqqa chiqmadi, natija: {ET.fromstring(ext_dtd).text}")
print("\n=== 4. Xavfsiz yechim ===")
print(" ishonchsiz XML uchun: pip install defusedxml")
print(" import defusedxml.ElementTree as ET → entity va DTD bloklanadi")
print("\n=== 5. Oqimli tahlil (iterparse) ===")
katta = "<lenta>" + "".join(f"<yozuv id='{i}'><ball>{i * 10}</ball></yozuv>" for i in range(1, 6)) + "</lenta>"
import io
jami = 0
korilgan = []
for hodisa, elem in ET.iterparse(io.StringIO(katta), events=("end",)):
if elem.tag == "yozuv":
jami += int(elem.findtext("ball"))
korilgan.append(elem.get("id"))
elem.clear() # ⭐ xotirani bo'shatish
print(f" qayta ishlangan yozuvlar: {korilgan}, jami ball: {jami}")
print(" ⚠️ elem.clear() bo'lmasa butun daraxt xotirada to'planadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. ⚠️ Entity kengayishi (billion laughs) ===
daraja 4: 3×2^4 = 48 belgi (XML manba ~8 qator)
daraja 8: 3×2^8 = 768 belgi (XML manba ~12 qator)
daraja 12: 3×2^12 = 12288 belgi (XML manba ~16 qator)
⚠️ har daraja ikki baravar — 30-daraja gigabaytlarga yetadi (xotira DoS)
=== 2. ✅ XXE — tashqi entity hal qilinmaydi ===
tashqi entity: undefined entity &x;
⭐ fayl o'qilmadi — stdlib tashqi entity ni hal qilmaydi (XXE dan xavfsiz)
=== 3. ✅ Tashqi DTD yuklanmaydi ===
tarmoqqa chiqmadi, natija: ok
=== 4. Xavfsiz yechim ===
ishonchsiz XML uchun: pip install defusedxml
import defusedxml.ElementTree as ET → entity va DTD bloklanadi
=== 5. Oqimli tahlil (iterparse) ===
qayta ishlangan yozuvlar: ['1', '2', '3', '4', '5'], jami ball: 150
⚠️ elem.clear() bo'lmasa butun daraxt xotirada to'planadiNima ko'rsatdi: 2.7, 2.8-bo'limlar.
Misol 4 — Amaliy: RSS lentani o'qib qayta ishlash
Ko'p sayt yangiliklarni RSS (XML) formatida beradi. Bizga hamkorlarning lentalarini o'qib, sanasi bo'yicha saralab, <content:encoded> (nom fazoli) va oddiy maydonlarni ajratib, ichki hisobotga aylantirish kerak. Lenta tashqi manbadan kelgani uchun uni ishonchsiz deb qaraymiz: tuzilishni tekshiramiz, yetishmayotgan maydonlarga bardosh beramiz va natijani JSON 16.2-bob ga chiqaramiz.
"""RSS/Atom-ga o'xshash XML: nom fazolari, findtext sukut bilan, sana tahlili va saralash, aralash maydonlar, ichki hisobotga (JSON) aylantirish."""
import json
import xml.etree.ElementTree as ET
from datetime import datetime
RSS = """<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Wisar Blog</title>
<item>
<title>Python 3.14 chiqdi</title>
<link>https://wisar.uz/p/314</link>
<pubDate>2026-09-15</pubDate>
<dc:creator>Aziz</dc:creator>
<category>python</category>
<category>yangilik</category>
<content:encoded>Yangi versiyada <b>bepul-tred</b> rejimi bor.</content:encoded>
</item>
<item>
<title>Type hints amaliyoti</title>
<link>https://wisar.uz/p/types</link>
<pubDate>2026-09-17</pubDate>
<dc:creator>Malika</dc:creator>
<category>python</category>
</item>
<item>
<title>Sarlavhasiz qoralama</title>
<pubDate>notogri-sana</pubDate>
</item>
</channel>
</rss>"""
NS = {"content": "http://purl.org/rss/1.0/modules/content/",
"dc": "http://purl.org/dc/elements/1.1/"}
def sana_ol(matn: str | None) -> datetime | None:
if not matn:
return None
try:
return datetime.strptime(matn.strip(), "%Y-%m-%d")
except ValueError:
return None
def maqola_ol(item: ET.Element) -> dict:
sana = sana_ol(item.findtext("pubDate"))
return {
"sarlavha": (item.findtext("title") or "").strip() or "(sarlavhasiz)",
"havola": item.findtext("link"),
"sana": sana.date().isoformat() if sana else None,
"muallif": item.findtext("dc:creator", namespaces=NS),
"teglar": [c.text for c in item.findall("category")],
"kontent_bormi": item.find("content:encoded", NS) is not None,
}
def main() -> None:
ildiz = ET.fromstring(RSS)
kanal = ildiz.find("channel")
print(f"=== 1. Lenta: {kanal.findtext('title')} ===")
itemlar = kanal.findall("item")
print(f" jami maqolalar: {len(itemlar)}")
maqolalar = [maqola_ol(item) for item in itemlar]
print("\n=== 2. Muammoli maqolalar ===")
for m in maqolalar:
muammolar = []
if m["sarlavha"] == "(sarlavhasiz)":
muammolar.append("sarlavha yo'q")
if m["sana"] is None:
muammolar.append("sana noto'g'ri")
if m["havola"] is None:
muammolar.append("havola yo'q")
if muammolar:
print(f" ⚠️ {m['sarlavha']}: {', '.join(muammolar)}")
print("\n=== 3. Sana bo'yicha saralangan (yangi birinchi) ===")
yaroqli = sorted((m for m in maqolalar if m["sana"]), key=lambda m: m["sana"], reverse=True)
for m in yaroqli:
teglar = ", ".join(m["teglar"]) or "—"
print(f" {m['sana']} {m['sarlavha']:26} [{teglar}] muallif: {m['muallif']}")
print("\n=== 4. Aralash kontent ===")
kontentli = ildiz.find(".//content:encoded", NS)
print(f" content:encoded matni: {kontentli.text!r}")
print("\n=== 5. Ichki hisobot (JSON) ===")
hisobot = {"manba": kanal.findtext("title"), "jami": len(maqolalar), "maqolalar": yaroqli}
print(json.dumps(hisobot, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Lenta: Wisar Blog ===
jami maqolalar: 3
=== 2. Muammoli maqolalar ===
⚠️ Sarlavhasiz qoralama: sana noto'g'ri, havola yo'q
=== 3. Sana bo'yicha saralangan (yangi birinchi) ===
2026-09-17 Type hints amaliyoti [python] muallif: Malika
2026-09-15 Python 3.14 chiqdi [python, yangilik] muallif: Aziz
=== 4. Aralash kontent ===
content:encoded matni: 'Yangi versiyada <b>bepul-tred</b> rejimi bor.'
=== 5. Ichki hisobot (JSON) ===
{
"manba": "Wisar Blog",
"jami": 3,
"maqolalar": [
{
"sarlavha": "Type hints amaliyoti",
"havola": "https://wisar.uz/p/types",
"sana": "2026-09-17",
"muallif": "Malika",
"teglar": [
"python"
],
"kontent_bormi": false
},
{
"sarlavha": "Python 3.14 chiqdi",
"havola": "https://wisar.uz/p/314",
"sana": "2026-09-15",
"muallif": "Aziz",
"teglar": [
"python",
"yangilik"
],
"kontent_bormi": true
}
]
}Nima ko'rsatdi: 2.2, 2.4, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "XML — JSON ning eski ko'rinishi" | Atribut/element farqi, aralash kontent, tartib bor |
"find('teg') doim ishlaydi" |
Nom fazosi bo'lsa {uri}teg kerak |
"<, & ni qo'lda almashtirish kerak" |
ElementTree avtomatik ekranlaydi |
"Belgilar orasidagi matn faqat text" |
Element keyingi matn — tail |
| "stdlib XML hujumlardan himoyalangan" | XXE dan — ha, entity kengayishidan — yo'q |
"ET.parse katta faylni yaxshi o'qiydi" |
Butun daraxtni yuklaydi — iterparse kerak |
"iterparse xotirani o'zi bo'shatadi" |
elem.clear() kerak |
"[1] — ikkinchi element" |
XPath da 1 dan — birinchi |
6. Keng tarqalgan xatolar va yechimlari
1. Nom fazosini unutish
ildiz.find("tranzaksiya") # ❌ None
ildiz.find("tranzaksiya", {"": "urn:iso:20022"}) # ✅2. Ishonchsiz XML ni stdlib bilan
ET.fromstring(tashqi_xml) # ⚠️ billion laughs
import defusedxml.ElementTree as ET # ✅ ishonchsiz manba uchun3. Katta faylni parse bilan
ET.parse("500mb.xml") # ❌ xotira
for _, e in ET.iterparse("500mb.xml", events=("end",)): # ✅
if e.tag == "yozuv": ...; e.clear()4. tail ni yo'qotish
"".join(e.text for e in ildiz) # ❌ oraliq matn yo'qoladi
"".join(ildiz.itertext()) # ✅5. None ni tekshirmaslik
kitob.find("narx").text # ❌ AttributeError agar yo'q bo'lsa
kitob.findtext("narx", default="0") # ✅6. Belgilarni qo'lda ekranlash
elem.text = matn.replace("<", "<") # ❌ ikki marta ekranlanadi
elem.text = matn # ✅ avtomatik7. Atribut turini son deb olish
narx = kitob.get("narx") + 1000 # ❌ str + int
narx = int(kitob.get("narx", "0")) + 1000 # ✅8. XPath indeksni 0 dan deb o'ylash
ildiz.find("kitob[0]") # ❌ SyntaxError yoki bo'sh
ildiz.find("kitob[1]") # ✅ birinchi7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 4.9-dars (o'tilgan): kodlashlar va XML deklaratsiyasi
- 16.2-dars (o'tilgan): JSON — XML ga zamonaviy muqobil
- 16.4-dars (o'tilgan):
pickle— entity kabi "kod bo'lgan ma'lumot" xavfi - 16.6-dars: YAML va TOML — sozlama formatlari
- 16.8-dars: katta fayllarni oqim bilan o'qish
- 22-qism: SOAP va eski veb-xizmatlar
- 26.3–26.4-darslar: web scraping — HTML/XML ni tahlil qilish
8. Eng yaxshi amaliyotlar
Nom fazolarini
namespaces=lug'at bilan boshqaring.Ishonchsiz XML —
defusedxml, stdlib emas.Katta fayllar —
iterparse+elem.clear().Belgilarni qo'lda ekranlamang.
findtext(..., default=...)bilan yo'q maydonlarga bardosh bering.Aralash kontentda
tail/itertextni hisobga oling.Yozishda
ET.indentva aniqencoding.Murakkab XPath yoki tez tahlil kerak bo'lsa —
lxml.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
import xml.etree.ElementTree as ET
r = ET.fromstring("<a x='1'><b>M</b><c/>T</a>")
1. print(r.tag, r.get("x"))
2. print(len(r))
3. print(r.findtext("b"))
4. print(r.find("c").text)
5. print(r[1].tail)
6. print(ET.tostring(ET.fromstring("<x>a&b</x>"), encoding="unicode"))
7. e = ET.Element("t"); e.text = "a<b"; print(ET.tostring(e, encoding="unicode"))
8. print(ET.fromstring("<n xmlns='u'><m/></n>").find("m"))
9. print(ET.fromstring("<n xmlns='u'><m/></n>").find("{u}m").tag)
10. print(ET.fromstring("<a><b/><b/></a>").findall("b").__len__())
11. print([x.text for x in ET.fromstring("<a><b>1</b><b>2</b></a>").iterfind("b")])
12. try:
ET.fromstring("<a><b></a>")
except ET.ParseError as e:
print(type(e).__name__)Javoblar
a 12MNoneT<x>a&b</x><t>a<b</t>None{u}m2['1', '2']ParseError
Vazifa 2: Xatolarni tuzating
1. def summa(xml_matn):
r = ET.fromstring(xml_matn)
return sum(k.find("narx").text for k in r.findall("kitob"))
2. def ismlar(xml_fayl):
r = ET.parse(xml_fayl).getroot() # 300 MB fayl
return [e.text for e in r.findall(".//ism")]
3. def oqi(tashqi_xml):
return ET.fromstring(tashqi_xml) # foydalanuvchi yuborgan
4. def topshiriq(r): # <hujjat xmlns="urn:x">
return r.find("tranzaksiya").get("id")
5. def yoz(sarlavha):
e = ET.Element("item")
e.text = "<b>" + sarlavha.replace("&", "&") + "</b>"
return ET.tostring(e, encoding="unicode")Javoblar
1. def summa(xml_matn):
r = ET.fromstring(xml_matn)
return sum(int(k.findtext("narx", "0")) for k in r.findall("kitob"))
2. def ismlar(xml_fayl):
natija = []
for _, e in ET.iterparse(xml_fayl, events=("end",)):
if e.tag == "ism":
natija.append(e.text)
e.clear()
return natija
3. import defusedxml.ElementTree as DET
def oqi(tashqi_xml):
return DET.fromstring(tashqi_xml) # entity/DTD bloklanadi
4. def topshiriq(r):
NS = {"": "urn:x"}
el = r.find("tranzaksiya", NS)
return el.get("id") if el is not None else None
5. def yoz(sarlavha):
e = ET.Element("item")
b = ET.SubElement(e, "b")
b.text = sarlavha # ekranlashni ET qiladi
return ET.tostring(e, encoding="unicode")Vazifa 3: XML ↔ JSON konvertor
- XML → JSON: atributlarni
@atr, matnni#text, takroriy elementlarni ro'yxat qiling - JSON → XML: teskari; nom fazolarini saqlang
- Aralash kontent (
text+tail) ni ham to'g'ri o'tkazing - Aylanib qaytish testi: XML → JSON → XML semantik teng bo'lsin
Vazifa 4: Sitemap generatori va validatori
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">yarating (URL,lastmod,priority)- 50 000 URL chegarasi va 50 MB hajm cheklovini tekshiring
- Mavjud sitemap ni o'qib, buzuq URL va sana formatlarini toping
- Katta sitemap ni
iterparsebilan tekshiring
Vazifa 5: Xavfsiz XML yuklovchi
xavfsiz_oqi(xml)—defusedxmlbo'lsa undan, bo'lmasa DTD ni rad etuvchi parser bilan- Entity kengayishini aniqlang: manba hajmi va natija hajmi nisbati chegarasi
- XXE urinishini jurnalga yozing (15.16)
lxmlningresolve_entities=Falsevarianti bilan solishtiring
Vazifa 6: .docx dan matn ajratish
.docx— zip ichidaword/document.xml(16.1 vazipfile)- Nom fazoli
<w:t>elementlaridan matnni ajrating - Paragraf (
<w:p>) larni qatorlarga bo'ling - 100 MB hujjatda
iterparsebilan xotirani o'lchang
Vazifa 7: O'ylash
XML "hamma narsani belgilash" g'oyasi bilan yaratildi va 2000-yillarda korporativ dunyoni egalladi (SOAP, XSD, XSLT, WS-*). Keyin JSON kelib, veb API larida uni deyarli butunlay siqib chiqardi. Nima uchun XML web da yutqazdi, lekin hujjatlar (Office, SVG), konfiguratsiya (Android) va korporativ integratsiyada (ISO 20022 to'lovlar) hamon yashaydi? XML ning qaysi kuchli tomonlari JSON da yo'q?
Javob
Qisqa javob: XML web API larida yutqazdi, chunki u ma'lumot uzatish uchun JSON dan og'irroq: teglar takrorlanadi, nom fazolari murakkab, brauzerda JSON.parse bepul ishlaydi. Lekin XML hujjat formati sifatida — matn, tuzilma va metama'lumot aralash bo'lgan joyda — JSON qila olmaydigan narsalarni qiladi: aralash kontent, sxema validatsiyasi (XSD), transformatsiya (XSLT), nom fazolari bilan modullilik. Shuning uchun u hujjat va tartibga solingan integratsiyada yashaydi.
1. Nega web da yutqazdi
| Sabab | Tafsilot |
|---|---|
| Og'irlik | Ochiluvchi/yopiluvchi teglar — JSON dan kattaroq |
| Brauzer | JSON.parse — tilning o'zida; XML uchun DOM API noqulay |
| Ma'lumot modeli | JSON to'g'ridan-to'g'ri obyekt/massivga mos, XML — hujjatga |
| Murakkablik | Nom fazolari, atribut/element farqi — ortiqcha yuk |
| Xavfsizlik | XXE, entity portlashi — qo'shimcha ehtiyot |
2. XML da bor, JSON da yo'q
| Imkoniyat | Tafsilot |
|---|---|
| Aralash kontent | Matn va elementlar aralashishi (hujjatlar uchun tabiiy) |
| Atribut vs element | Metama'lumot va kontent farqi |
| Nom fazolari | Turli sxemalarni bir hujjatda aralashtirmasdan birlashtirish |
| XSD | Kuchli, standart sxema validatsiyasi |
| XSLT | XML ni boshqa formatga deklarativ o'zgartirish |
| Izohlar, ishlov ko'rsatmalari | Hujjat metama'lumoti |
3. Nega hujjat va integratsiyada yashaydi
| Soha | Sabab |
|---|---|
Office (.docx, .xlsx) |
Aralash kontent, murakkab tuzilma, uzoq muddatli standart |
| SVG | Grafika — hujjat tabiati |
| Android tartib | Atribut/element, vositalar ekotizimi |
| ISO 20022 (to'lovlar) | Qat'iy XSD validatsiya, banklararo kelishuv |
| SOAP (eski tizimlar) | WS-* standartlari, inertsiya |
4. Muhandislik saboqlari
- Format vazifaga mos bo'lishi kerak: ma'lumot uzatish — JSON, hujjat — XML
- XML ning validatsiya va transformatsiya kuchi — qat'iy integratsiyada qimmatli
- Murakkablik narxi bor: nom fazolari, xavfsizlik — ehtiyot talab qiladi
- Yangi loyihada API — JSON; mavjud XML integratsiyasi — to'g'ri vositalar bilan (sxema, defusedxml, iterparse)
5. Xulosa
- XML web da og'irligi va JSON ning soddaligi tufayli yutqazdi
- Aralash kontent, XSD, XSLT, nom fazolari — JSON da yo'q kuchlar
- Hujjat, grafika, qat'iy integratsiyada XML yashaydi
- To'g'ri vosita tanlash — muhandis mahorati
Nimani mustahkamlaydi: 2.2–2.8-bo'limlar.
Xulosa
Bu darsda XML ni ElementTree bilan o'qish, yozish va uning xavflarini o'rgandik.
Eng muhim uch fikr:
ElementTree— o'qish, navigatsiya va qurish.fromstring/parsebilan o'qiladi,find/findall/findtextva XPath qism to'plami bilan navigatsiya qilinadi,Element/SubElement/tostringbilan quriladi.<,&kabi belgilar avtomatik ekranlanadi — qo'lda almashtirmang. Aralash kontentda element keyingi matntailda bo'ladi; butun matn uchunitertext.Nom fazolari — eng ko'p adashtiradigan joy.
xmlnsbo'lsa teg aslida{uri}tegbo'ladi va oddiyfind("teg")Noneqaytaradi. Yechim — nom fazolarininamespaces=lug'atga olish; yozishdaregister_namespace. Bank, to'lov va boshqa qat'iy integratsiyalarda bu doimiy uchraydi.XML xavfsizligi va katta fayllar. Python stdlib XXE (tashqi entity, fayl o'qish) dan sukut bo'yicha himoyalangan, lekin entity kengayishidan ("billion laughs") emas — ishonchsiz XML uchun
defusedxml. Katta fayllarniET.parsebutun daraxtni xotiraga yuklaydi; yagona to'g'ri yo'l —iterparseva har yozuvdan keyinelem.clear().
Keyingi darsda odam yozadigan sozlama formatlarini — YAML va TOML ni o'rganamiz: nega ular JSON dan qulay, YAML ning mashhur tuzoqlari (yes/no, norway muammosi, safe_load) va nega Python pyproject.toml uchun TOML ni tanladi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!