Warm tip: This article is reproduced from stackoverflow.com, please click
php xml xpath

PHP get nodes value with nested nodes XML

发布于 2020-03-27 10:31:50

I have a xml file:

<Epo>
<Doc upd="add">
<Fld name="IC"><Prg><Sen>A01B1/00 <Cmt>(1585, 779)</Cmt></Sen></Prg></Fld>
<Fld name="CC"><Prg><Sen>A01B1/00 <Cmt>(420, 54%)</Cmt>;</Sen><Sen>B25G1/102 <Cmt>(60, 8%)</Cmt>;</Sen><Sen>A01B1/02 <Cmt>(47, 6%)</Cmt></Sen></Prg></Fld></Doc>
<Doc upd="add">
<Fld name="IC"><Prg><Sen>A01B1/02 <Cmt>(3847, 1718)</Cmt></Sen></Prg></Fld>
<Fld name="CC"><Prg><Sen>A01B1/02 <Cmt>(708, 41%)</Cmt>;</Sen><Sen>A01B1/022 <Cmt>(347, 20%)</Cmt>;</Sen><Sen>A01B1/028 <Cmt>(224, 13%)</Cmt></Sen></Prg></Fld></Doc>
</Epo>

I want to get node value, for example : A01B1/00 (1585, 779) - A01B1/00 (420, 54%); B25G1/102 (60, 8%); A01B1/02 (47, 6%) Then formating them into table's column. how can I do that? My code:

<?php
    $doc = new DOMDocument;
    $doc->preserveWhiteSpace = false;
    $doc->load('test.xml'); //IPCCPC-epoxif-201905
    $xpath = new DOMXPath($doc);
    $titles = $xpath->query('//Doc/Fld'); 
        foreach ($titles as $title){
            echo $title->nodeValue ."<hr>";
            }
?>

I cannot separate evrey node. Please help me.

Questioner
Hàm Louis
Viewed
94
Nigel Ren 2019-07-04 13:46

I've tried to split it down to fetch all the various levels of content, but I think the main problem was just getting the current node text without the child elements text content. Using DOMDocument, the nodeValue is the same as textContent which (from the manual)...

textContent The text content of this node and its descendants.

Using DOMDocument isn't the easiest to use when just accessing a relatively simple hierarchy and requires you to continually make calls (in this case) to getElementsByTagName() to fetch the enclosed elements, the following source shows how you can get at each part of the document using this method...

foreach ( $doc->getElementsByTagName("Doc") as $item )    {
    echo "upd=".$item->getAttribute("upd").PHP_EOL;
    foreach ( $item->getElementsByTagName("Fld") as $fld )  {
        echo "name=".$fld->getAttribute("name").PHP_EOL;
        foreach ( $fld->getElementsByTagName("Sen") as $sen )  {
            echo trim($sen->firstChild->nodeValue) ." cmt = ".
                $sen->getElementsByTagName("Cmt")[0]->firstChild->nodeValue.PHP_EOL;
        }
    }
} 

Using the SimpleXML API can however give a simpler solution. Each level of the hierarchy is accessed using object notation, and so ->Doc is used to access the Doc elements off the root node, and the foreach() loops just work off that. You can also see that using just the element name ($sen->Cmt) will give you just the text content of that node and not the descendants (although you have to cast it to a string to get it's value from the object) ...

$doc = simplexml_load_file("test.xml");

foreach ( $doc->Doc as $docElemnt )    {
    echo "upd=".(string)$docElemnt['upd'].PHP_EOL;
    foreach ( $docElemnt->Fld as $fld )    {
        echo "name=".(string)$fld['name'].PHP_EOL;
        foreach ( $fld->Prg->Sen as $sen )    {
            echo trim((string)$sen)."=".trim((string)$sen->Cmt).PHP_EOL;
        }
    }
}