-3

I have this sample xml file:-

<products>
   <product_id value="1">
       <tab_id value="251">
            <dist_region value="5" />
            <dist_region value="10066" />
            <dist_region value="10069" />
       </tab_id>
   </product_id>
</products>

I am trying to get tab_id child element using XPathand I want result in set of child elements.

My expected output is as follows:-

dist_region,dist_region,dist_region

MY XPATH:-

$tab = $product->xpath('//tab_id/*');

Can anyone suggest what is the XPath to get child elements? Thanks.

Smile
  • 2,770
  • 4
  • 35
  • 57
Jack Php
  • 577
  • 2
  • 7
  • 25

2 Answers2

2

The xpath you tried works for me. So, Try the next code:

$sxml = new SimpleXMLElement($xml);
$xpath = $sxml->xpath('//tab_id/*');

$array = array();

foreach ($xpath as $child)
{
    $array[] = $child->getName();
}

echo implode(',',$array);

It gives you your desire output: dist_region,dist_region,dist_region.

Been $xml your XML file.

Luigi Siri
  • 2,068
  • 2
  • 19
  • 27
  • I slightly edited your answer: You don't need to cast an array to an array; (also) you should not cast anything to an array you foreach over (that is bad practice in PHP); `getName()` has the actual name of the element - not the value attribute. *If* you want to select all value attributes as array: `echo implode(',', $sxml->xpath('//tab_id/*/@value'));` - :-) – hakre May 20 '13 at 14:10
  • Thanks @hakre. I didn't knew that :) – Luigi Siri May 20 '13 at 14:46
  • @LuigiSiri if i want to all attribute then what i do? i am try this... `$tab = $product->xpath('//tab_id/ancestor::product_id/descendant-or-self::*/@*');` – Jack Php May 21 '13 at 05:45
  • and use this function attributes(); – Jack Php May 21 '13 at 05:50
  • If you want to get the value attribute, use the xpath hakre recommended: '//tab_id/*/@value'. And inside the for each just append $child to $array. _$array[] = $child;_ – Luigi Siri May 21 '13 at 12:17
  • @JackPhp, Did this answer was helpful back then? – Luigi Siri May 29 '13 at 12:15
1

Your XPath should be based on specific condition like value (if it is <tab_id id='256'> then more readable)

$result = $product->query('//tab_id[@value=' . $id . ']/*');

and then loop through it like below

if($result->length){
    foreach ($result as $item):
        echo "Value: ".$item['value'];
    echo "<hr>";
endforeach;
}
Smile
  • 2,770
  • 4
  • 35
  • 57
  • Why should there have to be a condition like `@value=' . $id . '`? There is no reason at all for that, you don't need IDs in XML – dirkk May 20 '13 at 13:13
  • `` to get a specific `tab_id` (if there are more) then we can get it. `$id` is assumed that it will be initialized by a required value. – Smile May 20 '13 at 13:17
  • Sure, but no one asked to get a specific `tab_id` element. Quite the contrary, as in the input example there is only one `tab_id` so having an id would be unnecessary. If there are multiple `tab_id`s, maybe one would process all of them. Or maybe there is some other condition. You are making assumptions which are not given anywhere. You don't need ids, this is not SQL. – dirkk May 20 '13 at 13:24
  • @dirkk I appreciate your feedback but I specified generic solution to keep in mind if there are more nodes and would have to pick specific one based on condition. Although not an issue. – Smile May 20 '13 at 13:26
  • Maybe one wants to process more nodes? There is nothing wrong about that. Your solution is not generic, it is in fact very specific. I am just picky about this, because people with little XML/XPath knowledge (and maybe a background in SQL) might think after reading your answer that you really should have some sort of id in XML, which is absolutely not true. – dirkk May 20 '13 at 13:32
  • 1
    Actually there are such XML files where `id`s are provided and users want to get specific node based on condition. So thought on that way. But I will sure keep your suggestion in mind next time. :) [Here](http://stackoverflow.com/questions/16648243/xml-domdocument-php-get-node-where-attribute-value) is one example. – Smile May 20 '13 at 13:36
  • @NullVoid: Even so if, this has been answered already on this website to a large extend. Reference the answer with a hyperlink instead of adding another one - especially as it is not clear what the OP asks for. – hakre May 20 '13 at 14:13
  • @hakre, Yes. Definitely. – Smile May 20 '13 at 14:39