Xpath Get Attribute Value in PHP

XPath get attribute value in PHP

XPath can do the job of getting the value attribute with $xpath->query("//input[@name='text1']/@value");. Then you can iterate over the node list of attribute nodes and access the $value property of each attribute node.

Get attribute values SimpleXML Xpath PHP

Not sure what you really try to do. As far as I understand...

$xml = simplexml_load_string($x); // assuming XML in $x
$hit = (string)$xml->xpath("/RESULTS/ROW[COLUMN/@NAME='ID' and COLUMN/text() = '001']/COLUMN[@NAME='NAME']")[0];

Above code step by step:

  • (string) will force the result to string, instead of object
  • xpath-expression: get <ROW> with a child <COLUMN> with an attribute NAME='ID' and a value of 001
  • starting from that specific <ROW>, select a child <COLUMN> with an attribute of NAME='NAME'
  • xpath() returns an array of SimpleXml elements, by [0] we select its first entry.
  • be aware that this code lacks checking if there's a match at all.

see it working: https://eval.in/503464

EDIT:

Re-read the question. To get the result you want, select the <ROW> and then iterate over the <COLUMN>:

$hit = $xml->xpath("/RESULTS/ROW[COLUMN/@NAME='ID' and COLUMN/text() = '001']")[0];
foreach ($hit as $column)
echo $column['NAME'] . ": " . $column . PHP_EOL;

Output:

ID: 001
NAME: ORG001
CODE: 1234

see https://eval.in/503493

Xpath query in PHP to attribute from element with specific attribute value

As it turns out from the chat conversation from my original question I had to register the namespace. In the end I used this website and the code turned out to be like this:

$feed = new DOMDocument();
$feed->load("http://www.wildstarfans.net/feeds/posts/default");

$xpath = new DOMXPath($feed);
$xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');

foreach ($xpath->evaluate('//atom:entry') as $entry) {

$href = $xpath->evaluate('string(atom:link[@rel="alternate"]/@href)', $entry);

}

Credits go to ThW and Wrikken. Wish I could give you guys SO points for this.

PHP XPath to get a part of an attribute value

As mentioned here and here, you unfortunately can't accomplish this in one query with XPath 1.0.

What you could do instead is list all the title attributes belonging to these <td>s, then use preg_match to grab anything that's after an = surrounded by spaces:

$rowTitleAttrs = $xmlSite->xpath('//tr[@class="showif_out"]/td/@title');

$phoneNumbers = [];
foreach ($rowTitleAttrs as $rowTitleAttr) {
if (preg_match('/(?<= = )(?<phoneNumber>.*?)$/', $rowTitleAttr->title, $matches)) {
$phoneNumbers[] = $matches['phoneNumber'];
}
}

I took the liberty of simplifying your XPath query in the process, as a class name should be accurate enough to not have to state the whole path leading to it.

Demo: https://3v4l.org/1oqqA

Getting Text Value of Data-Attribute Link in DOM XPath

Quite often I find it easiest to "inspect" the element I wish to target using the developer tools in Chrome from where it is possible to copy the XPath expression that targets that particular node. This doesn't always return the most useful XPath expression but it is usually a good starting point - in this case I tweaked the returned query and added in the classname.

Hope it helps

$term='dog show';
$url=sprintf('https://en.wikipedia.org/w/index.php?search=%s&title=Special:Search&fulltext=Search', urlencode( $term ) );

printf( '<a href="%s" target="_blank">%s</a>', $url, $url );

libxml_use_internal_errors(true);
$dom=new DOMDocument;
$dom->recover=true;
$dom->formatOutput=true;
$dom->preserveWhiteSpace=true;
$dom->strictErrorChecking=false;

$dom->loadHTMLFile( $url );
$xp=new DOMXPath( $dom );

/* possibly the important bit */
$query='//*[@id="mw-content-text"]/div/ul/li/div[@class="mw-search-result-heading"]/a';

$col=$xp->query( $query );

$html=array();

if( $col && $col->length > 0 ){
foreach( $col as $node ){
$html[]=array(
'title'=>$node->nodeValue,
'href'=>$node->getAttribute('href')
);
}
}

printf('<pre>%s</pre>',print_r($html,true));

Will output:

https://en.wikipedia.org/w/index.php?search=dog+show&title=Special:Search&fulltext=Search
Array(
[0] => Array
(
[title] => Dog show
[href] => /wiki/Dog_show
)

[1] => Array
(
[title] => Show dog
[href] => /wiki/Show_dog
)

[2] => Array
(
[title] => Westminster Kennel Club Dog Show
[href] => /wiki/Westminster_Kennel_Club_Dog_Show
)

[3] => Array
(
[title] => Dog Eat Dog (U.S. game show)
[href] => /wiki/Dog_Eat_Dog_(U.S._game_show)
)

.......... etc

XPATH Get Attribute of Current Node

You can achieve this by using getAttribute() method. Example:

foreach($nodeLIST as $node) {
$attribute = $node->getAttribute('class');
if($attribute == 'title') {
// do something
} elseif ($attribute == 'child') {
// do something
}
}

XPath to locate element based on attribute value?

As Micheal Kay has outlined in his answer, the xpath expression is valid. What he does not know is that for SimpleXML this won't lead into an empty result.

So you see a fatal error as you try to read a field from an empty array. Your code works similar to this one:

$found = array();
echo $found->state;

Which echoes an empty string (created out of the NULL value that expression give) and a notice:

Notice: Trying to get property of non-object in ...

If you don't see yet this notice, it's crucial you enable error messages with your development system, see How to get useful error messages in PHP?.

So as you can see, it is working properly, it just does not provide what you expect. To go on with that in a more productive manner for yourself, it would have been great if you would have shared what exactly you did expect instead.

Or in other words: As others have answered as well, you need to decide what you're looking for.

From the output code:

echo $found->state;

I'd say you're looking for the following XML element:

...
<repstate location="AK">
<compName>Test Company</compName>
<name>Chris Brown</name>
<address>123 Main St</address>
<city>Anytown</city>
<state>CT</state>
...

So here is how SimpleXML Xpath works:

  1. you can only query lists of nodes
  2. the only nodes supported are elements and attributes
  3. the list is always of type array
  4. the array is always zero-indexed
  5. each entry in the array - if the array is not empty - is of type SimpleXMLElement

So in your case if my assumption of the element to query you expect to get is correct, you want the state child-element's node value of a single element node returned. The according PHP code then would be:

$list = $xml->xpath("//repstate[@location = 'AK']");
list($repstate) = $list + array(null);
$state = $repstate ? $repstate->state : '- no such location -';

echo $state;

The output with your XML then would be:

CT

Or even shorter:

$list = $xml->xpath("//repstate[@location = 'AK']/state");
list($state) = $list + array('- no such location -');

echo $state;

I hope this more expansive explanation is helpful for you. The reason why your original expression does not work is that it's already violating the first point:

  1. you can only query lists of nodes

because your xpath query represented a boolean expression and not a node-list. Additionally such a list in SimpleXMLElement xpath would need you to have an element or attribute and not a boolean expression.

How can I get all attributes with PHP xpath?

In XPath, you can use @* to reference attributes of any name, for example :

$nodes = $xpath->query('//div/@*');

foreach ($nodes as $node) {
echo $node->nodeName ." : ". $node->nodeValue ."<br>";
}

eval.in demo

output :

class :  example-class
data-caption : Example caption
data-link : https://www.example.com
data-image-url : https://example.com/example.jpg

PHP/SimpleXML/XPath get attribute value by another attribute in same element

I think you problem might be the namespace. PPTX Relationship files use the namespace "http://schemas.microsoft.com/package/2005/06/relationships". But SimpleXmls xpath does it's own magic, too. If the file contains the namespace (check the source) you have to register an own prefix for it.

$xml = <<<'XML'
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Relationships
xmlns="http://schemas.microsoft.com/package/2005/06/relationships">
<Relationship Id="rId1"
Type="http://schemas.microsoft.com/office/2006/relationships/image"
Target="http://en.wikipedia.org/images/wiki-en.png"
TargetMode="External" />
<Relationship Id="rId2"
Type="http://schemas.microsoft.com/office/2006/relationships/hyperlink"
Target="http://www.wikipedia.org"
TargetMode="External" />
</Relationships>
XML;

$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
$xpath->registerNamespace('r', 'http://schemas.microsoft.com/package/2005/06/relationships');

var_dump(
$xpath->evaluate("string(/r:Relationships/r:Relationship[@Id='rId2']/@Target)", NULL, FALSE)
);

Output:

string(24) "http://www.wikipedia.org"

Xpath does not know something like a default namespace. Without a prefix you look for elements without any namespace. Attributes don't have a namespace if not explicitly prefixed.

To make the confusion complete, do the PHP functions (SimpleXMLElement::xpath(), DOMXpath::query() and DOMXpath::evaluate()) automatically register the namespace definitions of the used context. The third argument allows to disable that behaviour.

Unlike the other two functions, DOMXpath::evaluate() can return scalars directly.



Related Topics



Leave a reply



Submit