skip to Main Content

I would like to know how do I display these values from an api that returns me an xml. I’ve looked in some places, but it’s always one without the namespace and others with namespace… but mine has both and it always bugs and doesn’t display the values..

my xml:

<QTableGridDataSourceForMobileOfDocumentWBuH9k12 xmlns="http://schemas.datacontract.org/2004/07/Sinfic.DataContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<TotalRows>1</TotalRows>
<Rows xmlns:a="http://schemas.datacontract.org/2004/07/Sinfic.DataContracts.Documents">
<a:Document>
<a:a>6017</a:a>
<a:aa>135</a:aa>
<a:ab>-23.15749833</a:ab>
<a:ac>-45.79356167</a:ac>
<a:ad>6.80</a:ad>
<a:ai>0</a:ai>
<a:aj>Administrator</a:aj>  
<a:am>32872</a:am>
<a:an>Leonardo Righi</a:an>
<a:ao>16470252</a:ao>
<a:ap>16470108</a:ap>
<a:aq>
<a:data>
<a:key>
<a:id>d0180056-f7e6-4b13-8865-a963a9a131</a:id>
<a:tag>nomeTecnico</a:tag>
</a:key>
<a:value>Denis Rodrigues</a:value>
</a:data>
<a:ar>
<a:data>
<a:key>
<a:id>d6052d01-92b3-45a5-9059-f401eddf0ef5</a:id>
<a:tag>ImageAnswer</a:tag>
</a:key>
<a:value>27422</a:value>
</a:data>
</a:ar>
<a:b>150</a:b>
<a:bb>Manutenção Automáticas</a:bb>
<a:bc>02 - CELULARES</a:bc>
<a:bd>Cancelado</a:bd>
<a:bf>09/03/2022 14:52</a:bf>
<a:bg>11/03/2022 15:00</a:bg>
<a:bh>Automaticas</a:bh>
<a:bi>5</a:bi>
<a:bj>09/03/2022 14:41</a:bj>
<a:bk>09/03/2022 14:52</a:bk>
<a:bq>LOGISTICA LTDA</a:bq>
<a:br>2</a:br>
<a:bs>2</a:bs>
<a:bt>false</a:bt>
<a:bu>MyDocs</a:bu>
<a:bv># 1.4.17[14017]</a:bv>
<a:by>f1edqKgAgFWvOHGTmEFw42uggIDQt-K8pKPFaC6Em-Z7etzLOSr3Al6eCPndbg2</a:by>        
<a:cd>656</a:cd>
<a:ce>13235</a:ce>
<a:l>DENIS </a:l>
<a:o>f8b521e8-e92f-478e-a883</a:o>
</a:Document>
</Rows>
</QTableGridDataSourceForMobileOfDocumentWBuH9k12>

I tried this code, as close as I got:

<?php
$x = simplexml_load_file('teste.xml');
$campos = $x->
children('a', true)->
children('a', true);


foreach($campos as $chave => $valor){

echo $chave.' : '. $valor . '<br>';
    
}

?>

2

Answers


  1. You can access the children by giving the namespace or its prefix. I prefer the prefix, because it is shorter.

    Demo (previous): https://3v4l.org/VNt5d
    Demo (recursive): https://3v4l.org/uelMs

    Note

    Your data is still invalid. <a:aq> is not closed. So I removed it for my answer!

    $xml = simplexml_load_string($xmlText);
    
    function printKeyValue(string $key, SimpleXMLElement $value): void {
        echo "$key: ";
        if ($children = $value->children('a', true)) {
            foreach($children as $childKey => $childValue) {
                printKeyValue($childKey, $childValue);
            }
            return;
        }
        echo "$valuen";
    };
    
    foreach($xml->Rows->children('a', true) as $document) {
        foreach($document as $key => $value) {
            printKeyValue($key, $value);
        }
    }
    

    Output

    a: 6017
    aa: 135
    ab: -23.15749833
    ac: -45.79356167
    ad: 6.80
    ai: 0
    aj: Administrator
    am: 32872
    an: Leonardo Righi
    ao: 16470252
    ap: 16470108
    data: key: id: d0180056-f7e6-4b13-8865-a963a9a131
    tag: nomeTecnico
    value: Denis Rodrigues
    ar: data: key: id: d6052d01-92b3-45a5-9059-f401eddf0ef5
    tag: ImageAnswer
    value: 27422
    b: 150
    bb: Manutenção Automáticas
    bc: 02 - CELULARES
    bd: Cancelado
    bf: 09/03/2022 14:52
    bg: 11/03/2022 15:00
    bh: Automaticas
    bi: 5
    bj: 09/03/2022 14:41
    bk: 09/03/2022 14:52
    bq: LOGISTICA LTDA
    br: 2
    bs: 2
    bt: false
    bu: MyDocs
    bv: # 1.4.17[14017]
    by: f1edqKgAgFWvOHGTmEFw42uggIDQt-K8pKPFaC6Em-Z7etzLOSr3Al6eCPndbg2
    cd: 656
    ce: 13235
    l: DENIS 
    o: f8b521e8-e92f-478e-a883
    
    Login or Signup to reply.
  2. You mistake the namespaces prefixes with the actual namespace. The namespace definitions are the xmlns/xmlns:* attributes. Prefixes are optional for element nodes. The document element should be read as {http://schemas.datacontract.org/2004/07/Sinfic.DataContracts}QTableGridDataSourceForMobileOfDocumentWBuH9k12. Here are 3 examples that all resolve to this:

    • <QTableGridDataSourceForMobileOfDocumentWBuH9k12 xmlns="http://schemas.datacontract.org/2004/07/Sinfic.DataContracts">
    • <q:QTableGridDataSourceForMobileOfDocumentWBuH9k12 xmlns:q="http://schemas.datacontract.org/2004/07/Sinfic.DataContracts">
    • <qtable:QTableGridDataSourceForMobileOfDocumentWBuH9k12 xmlns:qtable="http://schemas.datacontract.org/2004/07/Sinfic.DataContracts">

    Namespaces can be redefined on any element node. So a prefix will only be valid until redefined. That makes it a really bad idea to rely on the prefixes in the document. Always use the namespace URI and/or define your own prefixes.

    SimpleXML does some implicit namespace handling in the background – like using the default namespace of the current context node. The explicit variant would look like this:

    const XMLNS_CONTRACTS = 'http://schemas.datacontract.org/2004/07/Sinfic.DataContracts';
    const XMLNS_DOCUMENT = 'http://schemas.datacontract.org/2004/07/Sinfic.DataContracts.Documents';
    
    $qTable = simplexml_load_string(getXMLString());
    
    foreach($qTable->children(XMLNS_CONTRACTS)->Rows->children(XMLNS_DOCUMENT) as $document) {
        foreach($document as $key => $value) {
            var_dump([$key, (string)$value]);
        }
    } 
    

    Or with DOM and Xpath:

    Take note that the example uses its own prefixes for the Xpath expressions. It only depends on the namespace URIs.

    const XMLNS_CONTRACTS = 'http://schemas.datacontract.org/2004/07/Sinfic.DataContracts';
    const XMLNS_DOCUMENT = 'http://schemas.datacontract.org/2004/07/Sinfic.DataContracts.Documents';
    
    $document = new DOMDocument();
    $document->loadXML(getXMLString());
    $xpath = new DOMXpath($document);
    $xpath->registerNamespace('c', XMLNS_CONTRACTS);
    $xpath->registerNamespace('d', XMLNS_DOCUMENT);
    
    foreach ($xpath->evaluate('//c:Rows/d:Document') as $rowsDocument) {
        foreach($xpath->evaluate('./d:*', $rowsDocument) as $cell) {
            var_dump(
                [$cell->localName, $cell->textContent]
            );
        }
    }
    

    The XML format is not a good one imho – so it might feel annoying to use. XML tags are supposed to be fixed and semantic. Dynamic tag names a big no go.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search