Hpple в Objective-C не может найти конкретный объект (XML/HTML Parser)

Для тех ветеранов, которые не пробовали Hpple, это здорово. Он использует Xpath для поиска в документах HTML/XML. Он выполняет свою работу, и его достаточно легко понять новичку вроде меня. Однако у меня проблемы.

У меня есть этот кусок HTML:

    <ul class="challengesList dailyChallengesList">

<li>
<div class="corner topLeft"></div>
<img id="ctl00_mainContent_dailyChallengesRepeater_ctl00_challengeImage" title="Gunslinger" src="/images/reachstats/challenges/0.png" alt="Gunslinger" style="border-width:0px;">
<div class="info">
<div class="rFloat">
<p id="ctl00_mainContent_dailyChallengesRepeater_ctl00_challengeExpiration" class="timeDisplay dailyExpirationCountdown"><span>0d</span><span>19h</span><span>9m</span><span class="seconds">37s</span></p>
<p>1500cR</p>
</div>
<h5>Gunslinger</h5>
<p class="description">Kill 150 enemies in multiplayer Matchmaking.</p>
<div class="reward">

<div id="ctl00_mainContent_dailyChallengesRepeater_ctl00_progressBox" class="barContainer">
<div id="ctl00_mainContent_dailyChallengesRepeater_ctl00_progressBar" class="bar" style="width:21%;"><span></span></div> 
<p>31/150</p>
</div>
</div>
</div>
<div class="clear"></div>
</li>

<li>
<div class="corner topLeft"></div>
<img id="ctl00_mainContent_dailyChallengesRepeater_ctl01_challengeImage" title="A Great Friend" src="/images/reachstats/challenges/0.png" alt="A Great Friend" style="border-width:0px;">
<div class="info">
<div class="rFloat">
<p id="ctl00_mainContent_dailyChallengesRepeater_ctl01_challengeExpiration" class="timeDisplay dailyExpirationCountdown"><span>0d</span><span>19h</span><span>9m</span><span class="seconds">37s</span></p>
<p>1400cR</p>
</div>
<h5>A Great Friend</h5>
<p class="description">Earn 15 assists today in multiplayer Matchmaking.</p>
<div class="reward">

<div id="ctl00_mainContent_dailyChallengesRepeater_ctl01_progressBox" class="barContainer">
<div id="ctl00_mainContent_dailyChallengesRepeater_ctl01_progressBar" class="bar" style="width:40%;"><span></span></div> 
<p>6/15</p>
</div>
</div>
</div>
<div class="clear"></div>
</li>

<li>
<div class="corner topLeft"></div>
<img id="ctl00_mainContent_dailyChallengesRepeater_ctl02_challengeImage" title="Cannon Fodder" src="/images/reachstats/challenges/2.png" alt="Cannon Fodder" style="border-width:0px;">
<div class="info">
<div class="rFloat">
<p id="ctl00_mainContent_dailyChallengesRepeater_ctl02_challengeExpiration" class="timeDisplay dailyExpirationCountdown"><span>0d</span><span>19h</span><span>9m</span><span class="seconds">37s</span></p>
<p>1000cR</p>
</div>
<h5>Cannon Fodder</h5>
<p class="description">Kill 50 infantry-class foes in the Campaign today.</p>
<div class="reward">

<div id="ctl00_mainContent_dailyChallengesRepeater_ctl02_progressBox" class="barContainer">
<div id="ctl00_mainContent_dailyChallengesRepeater_ctl02_progressBar" class="bar" style="width:0%;"><span></span></div> 
<p>0/50</p>
</div>
</div>
</div>
<div class="clear"></div>
</li>

<li>
<div class="corner topLeft"></div>
<img id="ctl00_mainContent_dailyChallengesRepeater_ctl03_challengeImage" title="Heroic Demon" src="/images/reachstats/challenges/3.png" alt="Heroic Demon" style="border-width:0px;">
<div class="info">
<div class="rFloat">
<p id="ctl00_mainContent_dailyChallengesRepeater_ctl03_challengeExpiration" class="timeDisplay dailyExpirationCountdown"><span>0d</span><span>19h</span><span>9m</span><span class="seconds">37s</span></p>
<p>1500cR</p>
</div>
<h5>Heroic Demon</h5>
<p class="description">Kill 30 Elites in Firefight Matchmaking on Heroic or harder.</p>
<div class="reward">

<div id="ctl00_mainContent_dailyChallengesRepeater_ctl03_progressBox" class="barContainer">
<div id="ctl00_mainContent_dailyChallengesRepeater_ctl03_progressBar" class="bar" style="width:0%;"><span></span></div> 
<p>0/30</p>
</div>
</div>
</div>
<div class="clear"></div>
</li>

</ul>

Суть в том, что я не могу заставить Hpple «увидеть» <div class="reward">. Я использую следующее, чтобы найти его:

NSArray * rawProgress = [doc search:@"//ul[@class='challengesList']
                                          /li/div[@class='info']
                                                 /div[@class='reward']/p"];

Это всегда возвращает пустой массив. Это сводит меня с ума, потому что то же самое работает со всеми остальными элементами этого проекта...

Любая помощь будет оценена по достоинству :)

ИЗМЕНИТЬ

Это работает:

NSArray * rawDescriptions = [doc search:@"//ul[@class='challengesList']
                                              /li/div[@class='info']
                                                     /p[@class='description']"];

Это не:

NSArray * rawProgress = [doc search:@"//ul[@class='challengesList']
                                          /li/div[@class='info']
                                                 /div[@class='reward']
                                                     /div[@id]//p"];

Кроме того, попытка перечислить дочерние узлы rFloat или вознаграждения приводит к сбою :(


person Aurum Aquila    schedule 07.12.2010    source источник
comment
Не забудьте поставить обратные кавычки вокруг элемента <div ...> в тексте вашего вопроса... исправили это за вас.   -  person LarsH    schedule 07.12.2010
comment
Это не было исправлено вашим редактированием. Я оставлю вам возможность поставить обратные кавычки там, где это необходимо, после «не могу заставить Hpple увидеть».   -  person LarsH    schedule 07.12.2010
comment
Можете ли вы опубликовать больше вашего входного HTML? И трижды проверьте, действительно ли то, что вы опубликовали, поступает в качестве входных данных?   -  person LarsH    schedule 07.12.2010
comment
Я вставил 4/5 входного HTML. Вы можете просмотреть полный исходный код по адресу: view-source:bungie. net/Stats/Reach/Challenges.aspx?player=Aurum+Aquila   -  person Aurum Aquila    schedule 07.12.2010
comment
Также обратите внимание, что исходная страница находится здесь: bungie.net/Stats. /Reach/Challenges.aspx?player=Aurum+Aquila   -  person Aurum Aquila    schedule 07.12.2010


Ответы (2)


Ваш элемент "p" не является непосредственным дочерним элементом div class="reward".

Используя предоставленный вами XML, выражение XPath

div[@class='info']/div[@class='reward']//p

буду работать.

person Flack    schedule 07.12.2010
comment
Спасибо за рекомендацию, но это возвращает нулевое значение. Я добавил пример выражения, которое действительно работает. - person Aurum Aquila; 07.12.2010
comment
@Aurum - @Flack прав в том, что ваш первый XPath, как указано, должен ничего не возвращать, потому что div[@class='reword'] не имеет непосредственного дочернего элемента p. - person LarsH; 07.12.2010
comment
Но проблема в том, что когда я прошу его перечислить потомков награды, в нем ничего нет. Когда я прошу его перечислить информацию, награда не появляется. - person Aurum Aquila; 07.12.2010

  • См. этот вопрос SO для аналогичного отчета о проблемах с Hpple и список альтернатив.

Возможно, вы видите ошибку. Согласно этой странице,

Он классифицируется разработчиком как экспериментальный проект, но пока он «у меня работает».

ОБНОВЛЕНИЕ: теперь кажется, что он сломан. У кого-нибудь есть лучшее решение?

Вы можете отправить отчет об ошибке, и, если проект все еще поддерживается, возможно, разработчик ответит исправлением или решением. Или вы можете оставить комментарий на эту страницу, которая рекомендовала hpple, и посмотрите, может ли этот блоггер или один из его читателей решить проблему или сказать вам, активен ли вообще hpple.

Вы также можете посмотреть, можете ли вы найти HyperParser. «Это простой анализатор HTML с API, похожим на NSXMLParser. Разработан специально для анализа полувалидного HTML». Но его, похоже, нет по ссылке, где он был раньше.

person LarsH    schedule 07.12.2010
comment
Да, это проблема с libxml. Я пытался использовать его прямо, с тем же результатом. Я думаю, что веб-сайт имеет искаженный HTML... Итак, я думаю о том, чтобы использовать чистый HTML или получить статистику от кого-то другого с лучшим HTML. - person Aurum Aquila; 08.12.2010
comment
Может ли это быть связано с тем, что теги img не закрыты? - person Aurum Aquila; 08.12.2010
comment
@Aurum: Кажется маловероятным, поскольку одно из ваших выражений XPath с li/div[@class='info'] работает, когда перед этим div стоит <img>. Но, исходя из того, что вы узнали о libxml, зачем полагаться на сломанную тростинку? HTMLTidy звучит как хорошее решение. - person LarsH; 08.12.2010
comment
Согласно сайту, HyperParser теперь является частью BaseAppKit, расположенного здесь: baseappkit.com. - person s73v3r; 04.01.2012