سؤال

يبدو ملف XML الخاص بي مثل ما يلي:

<?xml version="1.0"?>
<ItemSearchResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2008-08-19">
  <Items>
    <Item>
      <ItemAttributes>
        <ListPrice>
          <Amount>2260</Amount>
        </ListPrice>
      </ItemAttributes>
      <Offers>
        <Offer>
          <OfferListing>
            <Price>
              <Amount>1853</Amount>
            </Price>
          </OfferListing>
        </Offer>
      </Offers>
    </Item>
  </Items>
</ItemSearchResponse>

كل ما أريد القيام به هو استخراج ListPrice.

هذا هو الرمز الذي أستخدمه:

>> from elementtree import ElementTree as ET
>> fp = open("output.xml","r")
>> element = ET.parse(fp).getroot()
>> e = element.findall('ItemSearchResponse/Items/Item/ItemAttributes/ListPrice/Amount')
>> for i in e:
>>    print i.text
>>
>> e
>>

بالتأكيد لا إخراج. لقد حاولت أيضا

>> e = element.findall('Items/Item/ItemAttributes/ListPrice/Amount')

لا فرق.

ما الخطأ الذي افعله؟

هل كانت مفيدة؟

المحلول

هناك 2 مشاكل لديك.

1) element يحتوي فقط على عنصر الجذر، وليس بشكل متكرر المستند بأكمله. إنه عنصر النوع ليس entertree.

2) تحتاج سلسلة البحث إلى استخدام مساحات الأسماء إذا حافظت على مساحة الاسم في XML.

لإصلاح المشكلة رقم 1:

كنت بحاجة إلى تغيير:

element = ET.parse(fp).getroot()

ل:

element = ET.parse(fp)

لإصلاح المشكلة رقم 2:

يمكنك خلع XMLNs من مستند XML بحيث يبدو هذا:

<?xml version="1.0"?>
<ItemSearchResponse>
  <Items>
    <Item>
      <ItemAttributes>
        <ListPrice>
          <Amount>2260</Amount>
        </ListPrice>
      </ItemAttributes>
      <Offers>
        <Offer>
          <OfferListing>
            <Price>
              <Amount>1853</Amount>
            </Price>
          </OfferListing>
        </Offer>
      </Offers>
    </Item>
  </Items>
</ItemSearchResponse>

مع هذا المستند، يمكنك استخدام سلسلة البحث التالية:

e = element.findall('Items/Item/ItemAttributes/ListPrice/Amount')

الرمز الكامل:

from elementtree import ElementTree as ET
fp = open("output.xml","r")
element = ET.parse(fp)
e = element.findall('Items/Item/ItemAttributes/ListPrice/Amount')
for i in e:
  print i.text

الإصلاح البديل للمشكلة رقم 2:

وإلا تحتاج إلى تحديد XMLNs داخل سلسلة SREARCH لكل عنصر.

الرمز الكامل:

from elementtree import ElementTree as ET
fp = open("output.xml","r")
element = ET.parse(fp)

namespace = "{http://webservices.amazon.com/AWSECommerceService/2008-08-19}"
e = element.findall('{0}Items/{0}Item/{0}ItemAttributes/{0}ListPrice/{0}Amount'.format(namespace))
for i in e:
    print i.text

كلاهما طباعة:

2260

نصائح أخرى

from xml.etree import ElementTree as ET
tree = ET.parse("output.xml")
namespace = tree.getroot().tag[1:].split("}")[0]
amount = tree.find(".//{%s}Amount" % namespace).text

أيضا، فكر في استخدام lxml. وبعد انها طريقة أسرع.

from lxml import ElementTree as ET

تستخدم شجرة العنصر مساحات الأسماء بحيث تكون جميع العناصر الموجودة في XML لديك اسم مثل {http://webservices.amazon.com/awsecommerceservice/2008-08-19.}العناصر

لذلك اجعل البحث يشمل مساحة الاسم على سبيل المثال

search = '{http://webservices.amazon.com/AWSECommerceService/2008-08-19}Items/{http://webservices.amazon.com/AWSECommerceService/2008-08-19}Item/{http://webservices.amazon.com/AWSECommerceService/2008-08-19}ItemAttributes/{http://webservices.amazon.com/AWSECommerceService/2008-08-19}ListPrice/{http://webservices.amazon.com/AWSECommerceService/2008-08-19}Amount'
element.findall( search )

يعطي العنصر المقابل إلى 2260

انتهى بي الأمر تجريد xmlns من XML RAW مثل هذا:

def strip_ns(xml_string):
    return re.sub('xmlns="[^"]+"', '', xml_string)

من الواضح أن تكون حذرا جدا مع هذا، لكنها عملت بشكل جيد بالنسبة لي.

واحد من أكثر النهج المستمر للأمام والأعمال حتى مع بيثون 3.0 والإصدارات الأخرى مثل أدناه:

انها تأخذ فقط الجذر ويبدأ الدخول إليها حتى نحصل على علامة "المبلغ" المحدد

 from xml.etree import ElementTree as ET
 tree = ET.parse('output.xml')
 root = tree.getroot()
 #print(root)
 e = root.find(".//{http://webservices.amazon.com/AWSECommerceService/2008-08-19}Amount")
 print(e.text)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top