фильтровать извлеченные данные с помощью xpath - PullRequest
1 голос
/ 12 февраля 2012

я использую следующий код в качестве входных данных для документа dom

<li id="SalesRank">
<b>Amazon Best Sellers Rank:</b>
#20,267 Paid in Kindle Store (
<a href="http://www.amazon.com/gp/bestsellers/digital-text/ref=pd_dp_ts_kstore_1/190-9295683-0277616">See Top 100 Paid in Kindle Store</a>
) 
<ul class="zg_hrsr">
<li class="zg_hrsr_item">
<span class="zg_hrsr_rank">#15</span>
<span class="zg_hrsr_ladder">
in 
<a href="http://www.amazon.com/gp/bestsellers/digital-text/ref=pd_zg_hrsr_kstore_1_1">Kindle Store</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/154606011">Kindle eBooks</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/157325011">Nonfiction</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/292975011">Lifestyle & Home</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/156699011">Home & Garden</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/156828011">Gardening & Horticulture</a>
 > 
<b>
<a href="http://rads.stackoverflow.com/amzn/click/156847011">Greenhouses</a>
</b>
</span>
</li>
<li class="zg_hrsr_item">
<span class="zg_hrsr_rank">#26</span>
<span class="zg_hrsr_ladder">
in 
<a href="http://www.amazon.com/gp/bestsellers/digital-text/ref=pd_zg_hrsr_kstore_2_1">Kindle Store</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/154606011">Kindle eBooks</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/157325011">Nonfiction</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/292975011">Lifestyle & Home</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/156699011">Home & Garden</a>
 > 
<a href="http://rads.stackoverflow.com/amzn/click/156828011">Gardening & Horticulture</a>
 > 
<b>
<a href="http://rads.stackoverflow.com/amzn/click/156849011">House Plants</a>
</b>
</span>
</li>
</ul></li>

я использую следующий запрос xpath для извлечения данных с textContent ..

$xpath_cat->query('//li[@id="SalesRank"]');

вы можете проверитьвывод, он включает в себя данные, которые включены во все теги li с id=salrsrank..., в то время как я хочу получить только #20,267 paid in kindle store..

, поэтому требуется вывод

# 20,267 Оплачено в магазине Kindle

как мне изменить мой xpath для получения требуемого вывода?

Обновление в коде

Я попробовал решение, представленное ниже, и использовал xpath

$xpath_cat->query('//li[@id="SalesRank"]/text()');

, но теперь вывод:

([0] => [1] => #20,267 оплачено в магазине Kindle ([2] =>)

как я могу это исправить?

Ответы [ 2 ]

1 голос
/ 12 февраля 2012

Предположим, что $element равно DOMElement, содержащему <li id="SalesRank">...

Если вы делаете что-то вроде этого:

foreach( $element->childNodes as $node){
    echo get_class( $node) . "\n";
    // Print content too for debug:
    // echo $node->nodeValue . "\n";
}

Вы должны получить результаты вроде:

DOMText // \n
DOMElement // <b>Amazon Best Sellers Rank:</b>
DOMText // #20,267 Paid in Kindle Store (\n
DOMElement // <a ...
...

То есть $element->childNodes->item( 2)->nodeValue должен содержать вашу строку (делать домашнее задание, проверять каждую итерацию, проверять документацию для каждого элемента).

Чем вы можете просто получить строку до первого (:

$text = $element->childNodes->item( 2)->nodeValue;
$pos = strpos( $text, '(') - 2; // Add handling for no occurance
return substr( $text, 0, $pos);

Или вы можете перебрать все дочерние узлы и проверить это на лету

foreach( $element->childNodes as $node){
    // Example, rather use regexp with preg_match
    if( (get_class( $node) == 'DOMText')
        && (strncmp( $node->nodeValue, "\n#", 2) == 0)){
        // Tadaaa
        break;
    }
}

Или, если вам нужно решение, которое убьет несколько котят:

preg_match( '~(#([\d,]+) ([^<>(]+))~', $element->nodeValue, $match);
1 голос
/ 12 февраля 2012

Работает ли //li[@id='SalesRank']/text() у вас?

Обновление 1

Если нужный вам текст всегда будет в этом месте, тогда

substring-before(normalize-space(//li[@id='SalesRank']/text()[2]), ' (')

вернет

#20,267 Paid in Kindle Store

При этом normailize-space удаляет посторонние пробелы и substring-before выделяет весь текст перед первым появлением "(".

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

<b>Amazon Best Sellers Rank:</b>
<span>#20,267 Paid in Kindle Store</span> (
<a href="http://www.amazon.com/gp/bestsellers/digital-text/ref=pd_dp_ts_kstore_1/190-9295683-0277616">See Top 100 Paid in Kindle Store</a>
) 

<span/> не влияет на рендеринг и позволяет вам специально выбирать нужный текст.

Если второе решение работает не во всех случаях, и вы не можете получить целевой текст самостоятельно, у вас будет , чтобы полагаться на некоторую постобработку на языке хоста (PHP Iпредположим).

Надеюсь, это поможет,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...