سؤال

أنا أستخدم وحدة Python ElementTree المصممة. من السهل الوصول إلى الأطفال ، ولكن ماذا عن العقد الوالد أو الأخوة؟ - هل يمكن القيام بذلك بكفاءة دون عبور الشجرة بأكملها؟

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

المحلول

لا يوجد دعم مباشر في شكل أ parent السمة ، ولكن ربما يمكنك استخدام الأنماط الموصوفة هنا لتحقيق التأثير المطلوب. يتم اقتراح خط واحد التالي (من المنشور المرتبط) لإنشاء رسم خرائط من الطفل إلى الوالد لشجرة كاملة:

parent_map = dict((c, p) for p in tree.getiterator() for c in p)

نصائح أخرى

إجابة فيناي يجب أن لا يزال يعمل ، ولكن من أجل Python 2.7+ و 3.2+ يوصى بما يلي:

parent_map = {c:p for p in tree.iter() for c in p}

getiterator() تم إهماله لصالح iter(), ، ومن الجيد استخدام الجديد dict قائمة مُنشئ الفهم.

ثانياً ، أثناء إنشاء مستند XML ، من الممكن أن يكون لدى الطفل العديد من الآباء ، على الرغم من أن هذا يتم إزالته بمجرد إجراء تسلسل المستند. إذا كان ذلك مهمًا ، فقد تجرب هذا:

parent_map = {}
for p in tree.iter():
    for c in p:
        if c in parent_map:
            parent_map[c].append(p)
            # Or raise, if you don't want to allow this.
        else:
            parent_map[c] = [p]
            # Or parent_map[c] = p if you don't want to allow this

يمكنك استخدام XPath ... تدوين في ElementTree.

<parent>
     <child id="123">data1</child>
</parent>

xml.findall('.//child[@id="123"]...')
>> [<Element 'parent'>]

كما ذكر في احصل على عنصر الأصل بعد استخدام طريقة البحث (xml.etree.elementtree) سيكون عليك إجراء بحث غير مباشر عن الوالدين. وجود XML:

<a>
 <b>
  <c>data</c>
  <d>data</d>    
 </b>
</a>

على افتراض أنك قمت بإنشاء عنصر etree في xml متغير ، يمكنك استخدام:

 In[1] parent = xml.find('.//c/..')
 In[2] child = parent.find('./c')

مما أدى إلى:

Out[1]: <Element 'b' at 0x00XXXXXX> 
Out[2]: <Element 'c' at 0x00XXXXXX>

يمكن العثور على الوالدين العالي على النحو التالي:secondparent=xml.find('.//c/../..') مستخدم <Element 'a' at 0x00XXXXXX>

لا يمكن استخدام محدد XPath '..' لاسترداد العقدة الأصل في 3.5.3 ولا 3.6.1 (على الأقل على OSX) ، على سبيل المثال في الوضع التفاعلي:

import xml.etree.ElementTree as ET
root = ET.fromstring('<parent><child></child></parent>')
child = root.find('child')
parent = child.find('..') # retrieve the parent
parent is None # unexpected answer True

الجواب الأخير يكسر كل الآمال ...

طريقة أخرى إذا كانت تريد فقط الوالد الفرعي الواحد وأيضًا معروفة XPath's Subelement.

parentElement = subElement.find(xpath+"/..")

إذا كنت تستخدم LXML ، تمكنت من الحصول على العنصر الأصل بما يلي:

parent_node = next(child_node.iterancestors())

هذا سوف يرفع StopIteration استثناء إذا كان العنصر لا يحتوي على أسلاف - لذا كن مستعدًا للقبض على أنه إذا كنت قد تصادف هذا السيناريو.

لصق هنا إجابتي https://stackoverflow.com/a/54943960/492336:

واجهت مشكلة مماثلة وحصلت على خلاقة بعض الشيء. تبين أن لا شيء يمنعنا من إضافة معلومات النسب لأنفسنا. يمكننا لاحقًا تجريده بمجرد أن لا نحتاج إليه.

def addParentInfo(et):
    for child in et:
        child.attrib['__my_parent__'] = et
        addParentInfo(child)

def stripParentInfo(et):
    for child in et:
        child.attrib.pop('__my_parent__', 'None')
        stripParentInfo(child)

def getParent(et):
    if '__my_parent__' in et.attrib:
        return et.attrib['__my_parent__']
    else:
        return None

# Example usage

tree = ...
addParentInfo(tree.getroot())
el = tree.findall(...)[0]
parent = getParent(el)
while parent:
    doSomethingWith(parent)
    parent = getParent(parent)
stripParentInfo(tree.getroot())

انظر إلى 19.7.2.2. الجزء: بناء جملة XPath ...

ابحث عن والد العقدة باستخدام المسار:

parent_node = node.find('..')
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top