استعلام XPath مع نسل السليل ونص السليل ()
-
29-09-2019 - |
سؤال
أرغب في بناء استعلام XPath الذي سيعيد عنصر "Div" أو "الجدول" ، طالما أنه يحتوي على سليل يحتوي على النص "ABC". التحذير الوحيد هو أنه لا يمكن أن يكون لديه أي نسل Div أو طاولة.
<div>
<table>
<form>
<div>
<span>
<p>abcdefg</p>
</span>
</div>
<table>
<span>
<p>123456</p>
</span>
</table>
</form>
</table>
</div>
وبالتالي فإن النتيجة الصحيحة الوحيدة لهذا الاستعلام هي:
/div/table/form/div
أفضل محاولتي تبدو مثل هذا:
//div[contains(//text(), "abc") and not(descendant::div or descendant::table)] | //table[contains(//text(), "abc") and not(descendant::div or descendant::table)]
ولكن لا يعيد النتيجة الصحيحة.
شكرا لمساعدتك.
المحلول
أمر مختلف: :)
//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1]
يبدو أقصر بكثير من الحلول الأخرى ، أليس كذلك؟ قون
ترجم إلى اللغة الإنجليزية البسيطة: لأي عقدة نصية في المستند الذي يحتوي على السلسلة "abc"
حدد سلفه الأول الذي هو إما div
أو أ table
.
هذا أكثر كفاءة, ، حيث يلزم إجراء فحص كامل لشجرة المستندات (وليس أي شيء آخر) ، و ancestor::*
اجتياز رخيص جدًا مقارنة بـ descendent::
(شجرة) المسح.
للتحقق من أن هذا الحل "يعمل حقًا":
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select=
"//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1] "/>
</xsl:template>
</xsl:stylesheet>
عندما يتم تنفيذ هذا التحول على مستند XML المقدم:
<div>
<table>
<form>
<div>
<span>
<p>abcdefg</p>
</span>
</div>
<table>
<span>
<p>123456</p>
</span>
</table>
</form>
</table>
</div>
يتم إنتاج النتيجة الصحيحة المطلوبة:
<div>
<span>
<p>abcdefg</p>
</span>
</div>
ملحوظة: ليس من الضروري استخدام XSLT - أي مضيف XPath 1.0 - مثل DOM ، يجب أن تحصل على نفس النتيجة.
نصائح أخرى
//*[self::div|self::table]
[descendant::text()[contains(.,"abc")]]
[not(descendant::div|descendant::table)]
المشكلة مع contains(//text(), "abc")
هل هذه الوظائف المصبوبة بمجموعات العقدة تأخذ العقدة الأولى.
بامكانك ان تحاول:
//div[
descendant::text()[contains(., "abc")]
and not(descendant::div or descendant::table)
] |
//table[
descendant::text()[contains(., "abc")]
and not(descendant::div or descendant::table)
]
هل هذا يساعد؟