باستخدام XmlSlurper:كيفية تحديد العناصر الفرعية في حين بالتكرار على GPathResult

StackOverflow https://stackoverflow.com/questions/1675542

سؤال

أنا أكتب HTML محلل, والذي يستخدم TagSoup لتمرير جيدا شكلت هيكل XMLSlurper.

وهنا عمم كود:

def htmlText = """
<html>
<body>
<div id="divId" class="divclass">
<h2>Heading 2</h2>
<ol>
<li><h3><a class="box" href="#href1">href1 link text</a> <span>extra stuff</span></h3><address>Here is the address<span>Telephone number: <strong>telephone</strong></span></address></li>
<li><h3><a class="box" href="#href2">href2 link text</a> <span>extra stuff</span></h3><address>Here is another address<span>Another telephone: <strong>0845 1111111</strong></span></address></li>
</ol>
</div>
</body>
</html>
"""     

def html = new XmlSlurper(new org.ccil.cowan.tagsoup.Parser()).parseText( htmlText );

html.'**'.grep { it.@class == 'divclass' }.ol.li.each { linkItem ->
    def link = linkItem.h3.a.@href
    def address = linkItem.address.text()
    println "$link: $address\n"
}

أتوقع كل اسمحوا لي أن حدد كل 'لي' بدوره لذا يمكن استرداد المقابلة href وتفاصيل العنوان.بدلا من ذلك, أنا على الحصول على هذا الناتج:

#href1#href2: Here is the addressTelephone number: telephoneHere is another addressAnother telephone: 0845 1111111

لقد تحققت من مختلف سبيل المثال على شبكة الإنترنت و هذه إما التعامل مع XML أو بطانة واحدة أمثلة مثل "استرداد جميع الروابط من هذا الملف".يبدو أن it.h3.a.@href التعبير هو جمع كل hrefs في النص ، على الرغم من أنني يمر إشارة إلى الأم 'لي' عقدة.

يمكنك اسمحوا لي أن أعرف:

  • لماذا أنا على الحصول على الناتج هو مبين
  • كيف يمكنني استرداد href/أزواج عناوين لكل 'لي' البند

شكرا

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

المحلول

محل البقرى مع البحث:

html.'**'.find { it.@class == 'divclass' }.ol.li.each { linkItem ->
    def link = linkItem.h3.a.@href
    def address = linkItem.address.text()
    println "$link: $address\n"
}

ثم سوف تحصل على

#href1: Here is the addressTelephone number: telephone

#href2: Here is another addressAnother telephone: 0845 1111111

grep يعود ArrayList ولكن تجد ترجع NodeChild الدرجة:

println html.'**'.grep { it.@class == 'divclass' }.getClass()
println html.'**'.find { it.@class == 'divclass' }.getClass()

النتائج في:

class java.util.ArrayList
class groovy.util.slurpersupport.NodeChild

وهكذا إذا أردت استخدام البقرى ثم هل يمكن عش آخر مثل كل هذا من أجل أن تعمل

html.'**'.grep { it.@class == 'divclass' }.ol.li.each {
    it.each { linkItem ->
        def link = linkItem.h3.a.@href
        def address = linkItem.address.text()
        println "$link: $address\n"
    }
}

قصة قصيرة طويلة, في حالة استخدام تجد بدلا من البقرى.

نصائح أخرى

هذا هو واحد صعبة.عندما يكون هناك عنصر واحد فقط مع class='divclass' الإجابة السابقة بالتأكيد على ما يرام.إذا كانت هناك نتائج متعددة من البقرى ، ثم تجد() للحصول على نتيجة واحدة ليس هو الحل.مشيرا إلى أن النتيجة ArrayList هو الصحيح.إدراج الخارجي متداخلة .كل() حلقة يوفر GPathResult في إغلاق المعلمة div.من هنا أسفل يمكن أن تستمر مع النتيجة المتوقعة.

html."**".grep { it.@class == 'divclass' }.each { div -> div.ol.li.each { linkItem ->
   def link = linkItem.h3.a.@href
   def address = linkItem.address.text()
   println "$link: $address\n"
}}

سلوك رمز الأصلي يمكن استخدام أكثر قليلا من تفسير أيضا.عندما يمكن الوصول إلى مكان الإقامة على قائمة رائع, سوف تحصل على قائمة جديدة (نفس الحجم) مع خاصية كل عنصر في القائمة.وجدت قائمة من قبل البقرى() وقد إدخال واحد فقط.ثم نحصل على إدخال واحد على العقارات ol, التي على ما يرام.القادم نحصل على النتيجة من الرتب الأخرى.ذلك أن دخول.هو قائمة من حجم() == 1 مرة أخرى ، ولكن هذه المرة مع دخول حجم() == 2.ونحن يمكن أن تنطبق الحلقة الخارجية هناك والحصول على نفس النتيجة ، إذا أردنا أن:

html."**".grep { it.@class == 'divclass' }.ol.li.each { it.each { linkItem ->
   def link = linkItem.h3.a.@href
   def address = linkItem.address
   println "$link: $address\n"
}}

على أي GPathResult يمثلون عدة عقد, حصلنا على سلسلة من النص.هذا هو نتيجة الأصلية ، @href, ، ثم عنوان.

أعتقد أن الإجابات السابقة كلها صحيحة في وقت كتابة هذا التقرير، للإصدار المستخدم. لكنني أستخدم httpbuilder 0.7.1 وشجاع 2.4.4 مع Groovy 2.3.7 وهناك مشكلة كبيرة - يتم تحويل عناصر HTML إلى أحرف كبيرة. يبدو أن هذا بسبب Nekohtml المستخدمة تحت غطاء محرك السيارة:

http://nekohtml.sourceforge.net/faq.html#uppercase.

لهذا السبب، يجب كتابة الحل في الإجابة المقبولة على النحو التالي:

html.'**'.find { it.@class == 'divclass' }.OL.LI.each { linkItem ->
    def link = linkItem.H3.A.@href
    def address = linkItem.ADDRESS.text()
    println "$link: $address\n"
}

كان هذا محبطا للغاية لتصحيح الأخطاء، آمل أن يساعد شخص ما.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top