تحليل XML مع SimpleXML الذي يحتوي على مساحات أسماء متعددة [مكررة

StackOverflow https://stackoverflow.com/questions/740730

سؤال

لدي هذا XML القبيح الذي يحتوي على مساحات الأسماء الموجودة عليه، عندما أحاول تحميله مع SimpleXML إذا أشرت إلى مساحة الاسم الأولى التي أحصل عليها كائن XML، ولكن بعد العلامات مع مساحات الأسماء الأخرى لن تصل إلى الكائن.

كيف يمكنني تحليل هذا XML؟

<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
    <soap-env:Header>
        <eb:MessageHeader xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" eb:version="1.0" soap-env:mustUnderstand="1">
            <eb:From>
                <eb:PartyId eb:type="URI">wscompany.com</eb:PartyId>
            </eb:From>
            <eb:To>
                <eb:PartyId eb:type="URI">mysite.com</eb:PartyId>
            </eb:To>
            <eb:CPAId>something</eb:CPAId>
            <eb:ConversationId>moredata.com</eb:ConversationId>
            <eb:Service eb:type="compXML">theservice</eb:Service>
            <eb:Action>theaction</eb:Action>
            <eb:MessageData>
                <eb:MessageId>a certain messageid</eb:MessageId>
                <eb:Timestamp>2009-04-11T18:43:58</eb:Timestamp>
                <eb:RefToMessageId>mid:areference</eb:RefToMessageId>
            </eb:MessageData>
        </eb:MessageHeader>
        <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
            <wsse:BinarySecurityToken valueType="String" EncodingType="wsse:Base64Binary">an impresive binary security toekn</wsse:BinarySecurityToken>
        </wsse:Security>
    </soap-env:Header>
    <soap-env:Body>
        <SessionCreateRS xmlns="http://www.opentravel.org/OTA/2002/11" version="1" status="Approved">
            <ConversationId>the goodbye token</ConversationId>
        </SessionCreateRS>
    </soap-env:Body>
</soap-env:Envelope>

أنا أحاول تحليلها مع الكود التالي

<?php
$xml = simplexml_load_string($res,NULL,NULL,"http://schemas.xmlsoap.org/soap/envelope/");
?>

لكن كائن XML $ سيحتوي فقط على ما يلي

SimpleXMLElement Object
(
    [Header] => SimpleXMLElement Object
        (
        )

    [Body] => SimpleXMLElement Object
        (
        )

)
هل كانت مفيدة؟

المحلول

أعتقد أنك بحاجة إلى تسجيل Namespacing والوصول إلى XPath. شيء مثل ما يلي يجب أن تحصل على الذهاب (ليس لدي المرفق لاختبار هذا).

$xml = simplexml_load_string($res, NULL, NULL, "http://schemas.xmlsoap.org/soap/envelope/");
$xml->registerXPathNamespace('soap-env', 'http://schemas.xmlsoap.org/soap/envelope/');
$xml->registerXPathNamespace('eb', 'http://www.ebxml.org/namespaces/messageHeader');
$xml->registerXPathNamespace('wsse', 'http://schemas.xmlsoap.org/ws/2002/12/secext');

ثم يمكنك أن تفعل شيئا مثل:

foreach($xml->xpath('//eb:MessageHeader') as $header)
{
    var_export($header->xpath('//eb:CPAId')); // Should output 'something'.
}

قد لا تحتاج إلى تسجيل Namepacing، والتفكير في الأمر، لأنها موجودة في XML. لست متأكدا من ذلك، سيحتاج إلى اختبار.

أتمنى أن يساعدك هذا.

نصائح أخرى

1) لا تستخدم print_r والأصدقاء لمعرفة ما هو "في" كائن بسيط. يرى https://github.com/imsop/simplexml_debug. للشرح والبدائل.

2) دعم مساحة الاسم في SimpleXML مقدمة من قبل ->children() و ->attributes() طرق.

على سبيل المثال، يمكنك الحصول على PartyId of the node مثل هذا:

$from_party = (string)$xml->children('soap-env', true)->Header->children('eb', true)->MessageHeader->From->PartyId;

هذا مغلف صابون. قد ترغب في استخدام عميل SOAP إلى مجردة كل تحليل XML بعيدا. بي أتش بي يأتي مع عميل الصابون جيدة إلى حد ما شملت القيمة الافتراضية.

بالنسبة لأي شخص آخر يأتي عبر هذا، خدش رأسي في محاولة لإعادة البيانات الصحيحة وعلى الرغم من أن الإجابة العلوية كانت وثيقة للغاية، إلا أنها ما زلت أخذني بعض الوقت للعثور على الجواب. في نهاية المطاف تستخدم هذه الصفحة للمساعدة: https://www.w3schools.com/php/func_simplexml_registerxpathnamespace.asp.

أعتقد أن حلقة يمكنها الوصول مباشرة إلى ما تحتاج إليه. بمعنى آخر

foreach($xml->xpath('//eb:CPAId') as $header)
{
    echo $header; // Should output 'something'.
}

جرب هذا

   $soap_url = 'http://path/wsdl/somefile.wsdl';
   $soap_client = new SoapClient($soap_url);

   var_dump($soap_client->__getFunctions());

لمزيد من التفاصيل قرأت هنا

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top