سؤال

لدي ملف XML التالي، الملف كبير إلى حد ما، ولم أتمكن من الحصول على SimpleXML لفتح وقراءة الملف، لذلك أحاول XMLReader دون نجاح في PHP

<?xml version="1.0" encoding="ISO-8859-1"?>
<products>
    <last_updated>2009-11-30 13:52:40</last_updated>
    <product>
        <element_1>foo</element_1>
        <element_2>foo</element_2>
        <element_3>foo</element_3>
        <element_4>foo</element_4>
    </product>
    <product>
        <element_1>bar</element_1>
        <element_2>bar</element_2>
        <element_3>bar</element_3>
        <element_4>bar</element_4>
    </product>
</products>

لقد لم تجد للأسف تعليميا جيدا على هذا PHP وأحب أن أرى كيف يمكنني الحصول على محتوى كل عنصر لتخزينها في قاعدة بيانات.

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

المحلول

كل هذا يتوقف على حجم وحدة العمل الكبيرة، لكنني أعتقد أنك تحاول علاج كل منها <product/> العقد في الخلافة.

لذلك، ستكون أبسط طريقة لاستخدام xmlReader للوصول إلى كل عقدة، ثم استخدم SimpleXML للوصول إليها. بهذه الطريقة، يمكنك الاحتفاظ باستخدام الذاكرة منخفضة لأنك تتعامل مع عقدة واحدة في كل مرة وما زلت تستفيد سهولة استخدام SPALESXML. على سبيل المثال:

$z = new XMLReader;
$z->open('data.xml');

$doc = new DOMDocument;

// move to the first <product /> node
while ($z->read() && $z->name !== 'product');

// now that we're at the right depth, hop to the next <product/> until the end of the tree
while ($z->name === 'product')
{
    // either one should work
    //$node = new SimpleXMLElement($z->readOuterXML());
    $node = simplexml_import_dom($doc->importNode($z->expand(), true));

    // now you can use $node without going insane about parsing
    var_dump($node->element_1);

    // go to next <product />
    $z->next('product');
}

نظرة عامة سريعة على إيجابيات وسلبيات مناهج مختلفة:

XMLReader فقط

  • الايجابيات: سريع، يستخدم الذاكرة الصغيرة

  • السلبيات: من الصعب للغاية الكتابة والتصحيح، تتطلب الكثير من رمز userland للقيام بأي شيء مفيد. رمز UserLand بطيء وعرضة للخطأ. بالإضافة إلى ذلك، فإنه يتركك بمزيد من سطر من التعليمات البرمجية للحفاظ على

xmlReader + simplexml

  • الايجابيات: لا تستخدم الكثير من الذاكرة (فقط الذاكرة اللازمة لمعالجة عقدة واحدة) و SimpleXML، كما يعني الاسم، سهل الاستخدام حقا.

  • سلبيات: إنشاء كائن بسيط لكل عقدة ليست سريعة جدا. عليك حقا أن تقاسمها لفهم ما إذا كانت مشكلة بالنسبة لك. حتى آلة متواضعة ستكون قادرة على معالجة ألف عقد في الثانية، على الرغم من ذلك.

XMLREADER + DOM.

  • الايجابيات: يستخدم حول الكثير من الذاكرة مثل plassxml، و XMLReader :: توسيع () هو أسرع من إنشاء Simplexmlelement جديد. أتمنى لو كان من الممكن استخدام simplexml_import_dom() لكن يبدو أنه يعمل في هذه الحالة

  • سلبيات: دوم مزعج للعمل معه. انها في منتصف الطريق بين xmlreader و simplexml. ليست معقدة ومحرجة مثل xmlreader، ولكن سنوات ضوئية بعيدا عن العمل مع SimpleXML.

نصيحتي: اكتب نموذجا أوليا مع SimpleXML، راجع ما إذا كان يعمل من أجلك. إذا كان الأداء أمرا أساسيا، فجرب DOM. البقاء بعيدا عن XMLReader قدر الإمكان. تذكر أن مزيد من التعليمات البرمجية تكتبها، وكلما ارتفعت إمكانية إدخال الأخطاء أو إدخال تراجع الأداء.

نصائح أخرى

ل XML المنسق مع سمات ...

data.xml:

<building_data>
<building address="some address" lat="28.902914" lng="-71.007235" />
<building address="some address" lat="48.892342" lng="-75.0423423" />
<building address="some address" lat="58.929753" lng="-79.1236987" />
</building_data>

رمز PHP:

$reader = new XMLReader();

if (!$reader->open("data.xml")) {
    die("Failed to open 'data.xml'");
}

while($reader->read()) {
  if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'building') {
    $address = $reader->getAttribute('address');
    $latitude = $reader->getAttribute('lat');
    $longitude = $reader->getAttribute('lng');
}

$reader->close();

تم إنفاق معظم حياتي تحليل XML استخراج شذرات من المعلومات المفيدة من حمولة الشاحنات XML (Amazon MWS). على هذا النحو، تفترض إجابتي أنك تريد معلومات محددة فقط وأنت تعرف أين يقع.

أجد أسهل طريقة لاستخدام XMLReader هي معرفة العلامات التي أريدها المعلومات الخاصة بها واستخدامها. إذا كنت تعرف بنية XML ولديها الكثير من العلامات الفريدة، أجد أن استخدام الحالة الأولى سهلة. الحالات 2 و 3 هي فقط لتظهر لك كيف يمكن القيام به لمزيد من العلامات المعقدة. هذا سريع للغاية؛ لدي مناقشة من السرعة ما هو أسرع محلل XML في PHP؟

أهم شيء يجب تذكره عند القيام بتحليل تستند إلى العلامات مثل هذا هو استخدام if ($myXML->nodeType == XMLReader::ELEMENT) {... - الذي يتحقق للتأكد من أننا نتعامل فقط مع العقد الافتتاحية وليس مسافة تبديل أو إغلاق العقد أو أيا كان.

function parseMyXML ($xml) { //pass in an XML string
    $myXML = new XMLReader();
    $myXML->xml($xml);

    while ($myXML->read()) { //start reading.
        if ($myXML->nodeType == XMLReader::ELEMENT) { //only opening tags.
            $tag = $myXML->name; //make $tag contain the name of the tag
            switch ($tag) {
                case 'Tag1': //this tag contains no child elements, only the content we need. And it's unique.
                    $variable = $myXML->readInnerXML(); //now variable contains the contents of tag1
                    break;

                case 'Tag2': //this tag contains child elements, of which we only want one.
                    while($myXML->read()) { //so we tell it to keep reading
                        if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Amount') { // and when it finds the amount tag...
                            $variable2 = $myXML->readInnerXML(); //...put it in $variable2. 
                            break;
                        }
                    }
                    break;

                case 'Tag3': //tag3 also has children, which are not unique, but we need two of the children this time.
                    while($myXML->read()) {
                        if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Amount') {
                            $variable3 = $myXML->readInnerXML();
                            break;
                        } else if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Currency') {
                            $variable4 = $myXML->readInnerXML();
                            break;
                        }
                    }
                    break;

            }
        }
    }
$myXML->close();
}

أعطاني الإجابة المقبولة بداية جيدة، لكنها جلبت المزيد من الفصول وأكثر معالجة مما كنت أحب؛ لذلك هذا هو التفسير الخاص بي:

$xml_reader = new XMLReader;
$xml_reader->open($feed_url);

// move the pointer to the first product
while ($xml_reader->read() && $xml_reader->name != 'product');

// loop through the products
while ($xml_reader->name == 'product')
{
    // load the current xml element into simplexml and we’re off and running!
    $xml = simplexml_load_string($xml_reader->readOuterXML());

    // now you can use your simpleXML object ($xml).
    echo $xml->element_1;

    // move the pointer to the next product
    $xml_reader->next('product');
}

// don’t forget to close the file
$xml_reader->close();

XMLReader موثقة بشكل جيد على موقع فب. وبعد هذا هو محلل سحب XML، مما يعني أنه يستخدم للتكرار من خلال العقد (أو عقد DOM) من مستند XML معين. على سبيل المثال، يمكنك الذهاب من خلال المستند بأكمله الذي قدمته مثل هذا:

<?php
$reader = new XMLReader();
if (!$reader->open("data.xml"))
{
    die("Failed to open 'data.xml'");
}
while($reader->read())
{
    $node = $reader->expand();
    // process $node...
}
$reader->close();
?>

ثم يصل الأمر إليك لتحديد كيفية التعامل مع العقدة التي تم إرجاعها بواسطة XMLReader :: توسيع ().

Simple example:

public function productsAction()
{
    $saveFileName = 'ceneo.xml';
    $filename = $this->path . $saveFileName;
    if(file_exists($filename)) {

    $reader = new XMLReader();
    $reader->open($filename);

    $countElements = 0;

    while($reader->read()) {
        if($reader->nodeType == XMLReader::ELEMENT) {
            $nodeName = $reader->name;
        }

        if($reader->nodeType == XMLReader::TEXT && !empty($nodeName)) {
            switch ($nodeName) {
                case 'id':
                    var_dump($reader->value);
                    break;
            }
        }

        if($reader->nodeType == XMLReader::END_ELEMENT && $reader->name == 'offer') {
            $countElements++;
        }
    }
    $reader->close();
    exit(print('<pre>') . var_dump($countElements));
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top