1

I'm having trouble accessing a value from an XML file. Especially I can't extract the FrenchText. All I always get is the value from the GermanText. Does anyone have an idea, how to get to the value of the node containing the french string directly.

Consulting the web, I found this, but it only results in an error

echo $STRUCTURE_ITEM->NAME[@lang="fr"]

Any help would be greatly appreciated.

Here's my code

<?php

$myXMLData = '<?xml version="1.0" encoding="utf-8"?>
<CATALOG>
<CLASSIFICATION>
<STRUCTURE_ITEM> 
    <KEY>3605</KEY>  
    <NAME lang="de">GermanText1</NAME>  
    <NAME lang="fr">FrenchText1</NAME>  
    <PARENT_ID>worlds</PARENT_ID>  
    <SORT>0</SORT> 
  </STRUCTURE_ITEM>  
  <STRUCTURE_ITEM> 
    <KEY>3606</KEY>  
    <NAME lang="de">GermanText2</NAME>  
    <NAME lang="fr">FrenchText2</NAME>  
    <PARENT_ID>3605</PARENT_ID>  
    <SORT>0</SORT> 
</STRUCTURE_ITEM>
</CLASSIFICATION>
</CATALOG>';


$xml=simplexml_load_string($myXMLData);

foreach($xml->CLASSIFICATION->children() as $STRUCTURE_ITEM) { 
    echo $STRUCTURE_ITEM->KEY . ", "; 
    echo $STRUCTURE_ITEM->NAME . ", "; 
    echo $STRUCTURE_ITEM->NAME . ", "; // <---- The problem lies here
    echo $STRUCTURE_ITEM->PARENT_ID . "<br>"; 
} ;
?>

EDIT

Thanks for the valuable input. I've tried

$category_name_fr = $xml->xpath('//STRUCTURE_ITEM/NAME[@lang="fr"]');

Now I get the french values, but I get back an array containing all available french text. (FrenchText1, FrenchText2). But I just want the value of the current node.

fydelio
  • 932
  • 1
  • 8
  • 22
  • Seems to be a similar problem with this: http://stackoverflow.com/questions/15742457/simplexml-get-node-by-attribute – Rcls Mar 22 '15 at 15:30
  • 1
    `xpath` is your friend, see http://stackoverflow.com/questions/992450/simplexml-selecting-elements-which-have-a-certain-attribute-value – michi Mar 22 '15 at 16:42
  • Hi RCIS and Michi I've tried your input regarding xpath --> slowly getting there, but not quite there yet. Do you have any idea how not to get all values (array), but just the exact value of that one node. – fydelio Mar 22 '15 at 17:34
  • The answer is within the xpath itself. that particular xpath query `//` gets all nodes that data. Here's a reference tool: http://www.w3schools.com/xpath/ – nomistic Mar 22 '15 at 18:47

2 Answers2

1

Let me suggest an approach different from xpath: an inner foreach loop will iterate over all <NAME> and check for the lang attribute:

$lang = "fr";
foreach ($xml->CLASSIFICATION->STRUCTURE_ITEM as $item) { 
    echo $item->KEY . ", "; 

    foreach ($item->NAME as $name) 
        if ($name['lang'] == $lang) echo $name . ", ";        

    echo $item->PARENT_ID . "<br />";
}

See it in action: https://eval.in/303058

EDIT: If your XML is consistent meaning that de is always first and fr is always second, simply do:

$lang = 1; // 1 = fr, 0 = de
foreach ($xml->CLASSIFICATION->STRUCTURE_ITEM as $item) { 
    echo $item->KEY . ", "; 
    echo $item->NAME[$lang] . ", ";
    echo $item->PARENT_ID . "<br />";
}

See this in action: https://eval.in/303062

michi
  • 6,565
  • 4
  • 33
  • 56
0

Your xpath formula does something like this:
1. Starts from document root and proceeds in direction called 'descendant-or-self' (shortcut is //)
2. From this context searches in 'children' direction which is default (notice, that direction is not given after /) and looks for element called STRUCTURE_ITEM
3. From updated context (STRUCTURE_ITEM elements), xpath once more seeks for children elements, called NAME
4. Finally all nodes that fits ale checked with additional test (placed in []). Test says - check if there are nodes in 'attributes' direction (shortcut @). Nodes must be named 'fr'.

Because multiple nodes fits, results are concatenated. If you wish to extract NAME elements separately, try to shrink your initial context (don't start from document root [//]).

@edit:
this seems helpful: XPath query return multiple nodes on different levels

Community
  • 1
  • 1
Ghany
  • 43
  • 5