sabre-io / xml

sabre/xml is an XML library that you may not hate.
http://sabre.io/xml/
BSD 3-Clause "New" or "Revised" License
516 stars 77 forks source link

Parsing root element as key-value #135

Closed cnkt closed 6 years ago

cnkt commented 6 years ago

Hey! Thanks for this great library.

I have an xml file like that:

<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
    <soap-env:Header/>
    <soap-env:Body>
        <n0:Z_CRM_KDK_OPT_GET_SOZ_DETAILSResponse xmlns:n0="urn:sap-com:document:sap:rfc:functions">
            <ET_ITEMS>
                <item>
                    <ADRESE_TESLIM_KM>0000000000</ADRESE_TESLIM_KM>
                    <ADRESTEN_IADE_KM>0000000000</ADRESTEN_IADE_KM>
                    <STATUS>E0001</STATUS>
                    <USER_STAT_PROC>ZKDK_KLM</USER_STAT_PROC>
                </item>
            </ET_ITEMS>
        </n0:Z_CRM_KDK_OPT_GET_SOZ_DETAILSResponse>
    </soap-env:Body>
</soap-env:Envelope>

And i'm parsing it like that:

function testXmlParse()
{
    $reader = new Sabre\Xml\Reader();
    $xmlResult = file_get_contents(APP_ROOT . '/sample.xml');

    $reader->elementMap = [
        '{http://schemas.xmlsoap.org/soap/envelope/}Envelope' => function(Sabre\Xml\Reader $reader) {
            return Sabre\Xml\Deserializer\keyValue($reader, 'http://schemas.xmlsoap.org/soap/envelope/');
        },
        '{http://schemas.xmlsoap.org/soap/envelope/}Body' => function(Sabre\Xml\Reader $reader) {
            return Sabre\Xml\Deserializer\keyValue($reader, 'urn:sap-com:document:sap:rfc:functions');
        },
        '{}item' => function(Sabre\Xml\Reader $reader) {
            return Sabre\Xml\Deserializer\keyValue($reader, '');
        },
        '{}ET_ITEMS' => function(Sabre\Xml\Reader $reader) {
            return Sabre\Xml\Deserializer\repeatingElements($reader, '{}item');
        },
        '{urn:sap-com:document:sap:rfc:functions}Z_CRM_KDK_OPT_GET_SOZ_DETAILSResponse' => function(Sabre\Xml\Reader $reader) {
            return Sabre\Xml\Deserializer\keyValue($reader, '');
        }
    ];
    $reader->XML($xmlResult);

    $result = $reader->parse();

    dump($result);
}

And the result is like that:

array:3 [
  "name" => "{http://schemas.xmlsoap.org/soap/envelope/}Envelope"
  "value" => array:2 [
    "Header" => null
    "Body" => array:1 [
      "Z_CRM_KDK_OPT_GET_SOZ_DETAILSResponse" => array:1 [
        "ET_ITEMS" => array:1 [
          0 => array:4 [
            "ADRESE_TESLIM_KM" => "0000000000"
            "ADRESTEN_IADE_KM" => "0000000000"
            "STATUS" => "E0001"
            "USER_STAT_PROC" => "ZKDK_KLM"
          ]
        ]
      ]
    ]
  ]
  "attributes" => []
]

Envelope element itself is the root and i want it to be a key-value pair too. like that:

array:1 [
  "Envelope" => array:2 [
    "Header" => null
    "Body" => array:1 [
      "Z_CRM_KDK_OPT_GET_SOZ_DETAILSResponse" => array:1 [
        "ET_ITEMS" => array:1 [
          0 => array:4 [
            "ADRESE_TESLIM_KM" => "0000000000"
            "ADRESTEN_IADE_KM" => "0000000000"
            "STATUS" => "E0001"
            "USER_STAT_PROC" => "ZKDK_KLM"
          ]
        ]
      ]
    ]
  ]
]
evert commented 6 years ago

Sorry for the big delay. I haven't really been monitoring this as much.

Deserializers can only work on the 'content' of an element, not the element itself that's why it doesn't work on that level.

However, you are completely free in using all the apis as you see fit. For example, Sabre\Xml\Service::expect also reads an xml document and reformats the result:

https://github.com/sabre-io/xml/blob/master/lib/Service.php#L138

So I'll just ask the obvious question... why don't you build a function that does exactly what you want?

function foo($input) {
   $server = new Sabre\Xml\Service();
   $result = $server->parse($input);
   return [$result['name'] => $result['value'];
}

However, the expect function might be even a bit better for your use-case.