0

I've tried the solution here: Getting attribute using XPath but it gives me an error.

I have some XHTML like this:

<a href="link.php">Click me!</a>

I'm recursively parsing the XML and trying to get both the href attribute (link.php) and the link text (Click me!) at the same time.

<?php
$node = $xpath->query('string(self::a/@href) | self::a/text()', $nodes->item(0));

This code throws the following error:

Warning: DOMXPath::query(): Invalid type

If I do either of these two separately they work, but not together:

<?php
$node = $xpath->evaluate('string(self::a/@href)', $nodes->item(0));
$node = $xpath->query('self::a/text()', $nodes->item(0));

If I use the following I get the whole attribute (href="link.php"), not just its value:

<?php
$node = $xpath->query('self::a/@href | self::a/text()', $nodes->item(0));

Is there any way of getting both text values at the same time using XPath 1.0 in PHP?

Community
  • 1
  • 1
CJ Dennis
  • 4,226
  • 2
  • 40
  • 69
  • make him become a string :) - concat(a/@href , '|',a/text()) – splash58 Mar 22 '16 at 13:44
  • @splash58 That gives me no matches at all. Was it supposed to be a serious suggestion? – CJ Dennis Mar 22 '16 at 13:50
  • I do not think php xpaht will support concat. Also I do not see why you try to do this with xpath (I like xpath). You seem allready to have the right DomNode. So why not use `->getAttribute` and `->node_value` ? – hr_117 Mar 22 '16 at 14:02
  • @hr_117 You are perfectly correct! It's been a while since I've used XPath and I've forgotten a lot of it. I just refactored my code as you suggested a few minutes ago. Sorry I can't give you credit for that! – CJ Dennis Mar 22 '16 at 14:05
  • @hr_117 yuo are right - does not support. i just tried that – splash58 Mar 22 '16 at 14:05
  • 1
    @splash58 , @hr_117 `concat()` is *actually supported* by PHP XPath processor, see [the demo](https://eval.in/540784) (the same link as in my answer below) – har07 Mar 23 '16 at 03:32
  • @har07 my mistake was using query instead of evaluate. By the way, you can use only one step `$node = $xpath->evaluate('concat(//a/@href, "|", //a)');` – splash58 Mar 23 '16 at 04:56

1 Answers1

1

As suggested by others, you can use concat() (and PHP XPath supports it! see the demo below) to combine value of attribute and content of an element.

The problem with others' suggested XPath probably was, judging from your attempted code i.e the use of self::a, that the context node ($nodes->item(0)) is already the <a> element, so that a/@href relative to current context node means return href attribute of child element a of current element, that's why you got no match. You were correct by using self::a in this case or, alternatively, just . which can be used to reference current context node :

$doc = new DOMDocument();
$xml = <<<XML
<root>
<a href="link.php">Click me!</a>
</root>
XML;

$doc->loadXML($xml);
$xpath = new DOMXpath($doc);
$nodes = $xpath->query('//a');

$node = $xpath->evaluate('concat(@href, "|", .)', $nodes->item(0));
echo $node;

eval.in demo

output :

link.php|Click me!
har07
  • 88,338
  • 12
  • 84
  • 137