سؤال
أنا أستخدم XPath في .NET لتحليل مستند XML، على غرار ما يلي:
XmlNodeList lotsOStuff = doc.SelectNodes("//stuff");
foreach (XmlNode stuff in lotsOStuff) {
XmlNode stuffChild = stuff.SelectSingleNode("//stuffChild");
// ... etc
}
تكمن المشكلة في أن استعلام XPath لـ stuffChild
هو دائما يعود الطفل الأول stuff
عنصر، أبدا الباقي.لا يمكن استخدام XPath للاستعلام ضد فرد ما XMLElement
?
المحلول
//
في بداية تعبير XPath يبدأ من جذر المستند.جرب ".//stuffChild"..هو اختصار لـ self::node()، والذي سيحدد سياق البحث، و// هو اختصار للمحور التنازلي.
لذلك لديك:
XmlNode stuffChild = stuff.SelectSingleNode(".//stuffChild");
والذي يترجم إلى:
xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant::stuffChild");
xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant-or-self::stuffChild");
في الحالة التي يمكن أن تحمل فيها العقدة الفرعية نفس اسم العقدة الأصل، قد ترغب في استخدام بناء الجملة المطول قليلاً التالي، لضمان عدم إعادة تحديد العقدة الأصل:
xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant::stuffChild");
لاحظ أيضًا أنه إذا كان "stuffChild" سليلًا مباشرًا لـ "stuff"، فيمكنك حذف البادئات تمامًا، واختيار "stuffChild" فقط.
XmlNode stuffChild = stuff.SelectSingleNode("stuffChild");
ال W3Schools يحتوي البرنامج التعليمي على معلومات مفيدة بتنسيق سهل الهضم.
نصائح أخرى
ال //
تستخدمه أمام stuffChild
يعني أنك تبحث عنه stuffChild
العناصر تبدأ من الجذر.
إذا كنت تريد البدء من العقدة الحالية (أبناء العقدة الحالية)، فيجب عليك استخدام .//
, ، كما في:
stuff.SelectSingleNode(".//stuffChild");
إذا كانت "stuffChild" عبارة عن عقدة فرعية لـ "stuff"، فيجب أن يكون xpath الخاص بك هو:
XmlNode stuffChild = stuff.SelectSingleNode("stuffChild");
تحديد عقدة واحدة يعني أنك تحتاج إلى العنصر الأول فقط.إذن الحل الأفضل هو:
XmlNode stuffChild = stuff.SelectSingleNode("descendant::stuffChild[1]");