PHP में XMLReader का उपयोग कैसे करें?


79

मेरे पास निम्न XML फ़ाइल है, फ़ाइल बड़ी है और मैं फ़ाइल को खोलने और पढ़ने में सरल नहीं हो पा रहा हूँ इसलिए मैं 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 के लिए इस पर एक अच्छा ट्यूटोरियल नहीं मिला है और यह देखना अच्छा लगेगा कि मैं डेटाबेस में स्टोर करने के लिए प्रत्येक तत्व सामग्री कैसे प्राप्त कर सकता हूं।


1
क्या आपने PHP प्रलेखन में उपयोगकर्ता द्वारा योगदान किए गए कुछ उदाहरणों को पढ़ा है? php.net/manual/en/class.xmlreader.php#61929 मदद कर सकता है।
mcrumley

जवाबों:


225

यह सब इस बात पर निर्भर करता है कि काम की इकाई कितनी बड़ी है, लेकिन मुझे लगता है कि आप <product/>उत्तराधिकार में प्रत्येक नोड का इलाज करने की कोशिश कर रहे हैं ।

उसके लिए, प्रत्येक नोड पर जाने के लिए XMLReader का उपयोग करना सबसे सरल तरीका होगा, फिर उन्हें एक्सेस करने के लिए SimpleXML का उपयोग करें। इस तरह, आप मेमोरी उपयोग को कम रखते हैं क्योंकि आप एक बार में एक नोड का इलाज कर रहे हैं और आप अभी भी सिम्पलेक्स के उपयोग में आसानी का लाभ उठाते हैं। उदाहरण के लिए:

$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 ही

  • पेशेवरों: तेज, छोटी मेमोरी का उपयोग करता है

  • विपक्ष: लिखने और डिबग करने के लिए अत्यधिक कठिन, उपयोगी कुछ भी करने के लिए बहुत सारे उपयोगकर्ता कोड की आवश्यकता होती है। उपयोगकर्तालैंड कोड धीमा है और त्रुटि का खतरा है। साथ ही, यह आपको बनाए रखने के लिए कोड की अधिक लाइनों के साथ छोड़ देता है

XMLReader + SimpleXML

  • पेशेवरों: बहुत स्मृति का उपयोग नहीं करता (केवल एक नोड को संसाधित करने के लिए आवश्यक मेमोरी) और SimpleXML है, जैसा कि नाम का तात्पर्य है, वास्तव में उपयोग करना आसान है।

  • विपक्ष: प्रत्येक नोड के लिए एक SimpleXMLElement ऑब्जेक्ट बनाना बहुत तेज़ नहीं है। आपको वास्तव में यह समझने के लिए बेंचमार्क करना होगा कि क्या यह आपके लिए समस्या है। हालांकि एक मामूली मशीन प्रति सेकंड एक हजार नोड्स को संसाधित करने में सक्षम होगी।

XMLReader + DOM

  • पेशेवरों: SimpleXML के रूप में ज्यादा के बारे में स्मृति का उपयोग करता है, और XMLReader :: का विस्तार () एक नया SimpleXMLElement बनाने की तुलना में तेज है। काश इसका उपयोग संभव simplexml_import_dom()होता लेकिन यह उस मामले में काम नहीं करता

  • विपक्ष: डोम के साथ काम करने के लिए कष्टप्रद है। यह XMLReader और SimpleXML के बीच आधा है। XMLReader जितना जटिल और अटपटा नहीं है, लेकिन SimpleXML के साथ काम करने से प्रकाश वर्ष दूर है।

मेरी सलाह: SimpleXML के साथ एक प्रोटोटाइप लिखें, देखें कि क्या यह आपके लिए काम करता है। यदि प्रदर्शन सर्वोपरि है, तो DOM आज़माएँ। जितना हो सके XMLReader से दूर रहें। याद रखें कि आप जितना अधिक कोड लिखेंगे, आपके द्वारा बगों को पेश करने या प्रदर्शन प्रतिगमन शुरू करने की संभावना उतनी ही अधिक होगी।


1
क्या XMLReader के साथ शुद्ध रूप से ऐसा करने का कोई तरीका है या कोई फायदा नहीं है?
Shadi Almosri

2
आप इसे पूरी तरह से XMLReader के साथ कर सकते हैं। लाभ यह है कि यह तेज होगा और थोड़ी कम मेमोरी का उपयोग करेगा। इसका नुकसान यह है कि इसे लिखने में काफी समय लगेगा और डीबग करना बहुत कठिन होगा।
जोश डेविस

2
जब आप पहले उत्पाद नोड पर जाते हैं तो आपने $ z-> अगला ('उत्पाद') का उपयोग क्यों नहीं किया?
लाल

मुझे वह विशिष्ट कोड याद नहीं है, क्षमा करें। अगर मैंने इसके बारे में कोई नोट नहीं जोड़ा, तो हो सकता है कि मैं इस संभावना को नजरअंदाज कर दूं।
जोश डेविस

1
XMLReader आधारित पार्सिंग के अधिकांश को इट्रेटर पैटर्न में व्यक्त / लपेटा जा सकता है। मैंने इसके लिए कुछ उपयोगी पुनरावृत्तियों और फ़िल्टर संकलित किए हैं: git.io/xmlreaderiterator ( gist )
hakre 5'13 '23:

10

विशेषताओं के साथ 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();

1
हालांकि कोड एक्सएमएल के माध्यम से चलने के लिए एक बहुत अधिक क्रिया और मैनुअल तरीका है, इससे आपकी पवित्रता बच जाएगी, क्योंकि DOMDocument और SimpleXML आपको यह अनुमान लगाने के लिए रखते हैं कि क्या लौटाया जाएगा।
b01

6

स्वीकृत उत्तर ने मुझे एक अच्छी शुरुआत दी, लेकिन मैं जितना पसंद करता था उससे अधिक कक्षाओं और अधिक प्रसंस्करण में लाया; तो यह मेरी व्याख्या है:

$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();

6

मेरे एक्सएमएल पार्सिंग जीवन का अधिकांश हिस्सा एक्सएमएल (अमेज़ॅन एमडब्ल्यूएस) के ट्रक लोड से उपयोगी सूचनाओं की डली निकालने में व्यतीत होता है। जैसे, मेरा उत्तर मानता है कि आप केवल विशिष्ट जानकारी चाहते हैं और आप जानते हैं कि यह कहाँ स्थित है।

मुझे XMLReader का उपयोग करने का सबसे आसान तरीका पता है कि मुझे कौन से टैग से जानकारी प्राप्त करनी है और उनका उपयोग करना है। यदि आप XML की संरचना को जानते हैं और इसमें बहुत सारे अनूठे टैग हैं, तो मुझे लगता है कि पहले मामले का उपयोग करना आसान है। मामले 2 और 3 आपको केवल यह दिखाने के लिए हैं कि इसे और अधिक जटिल टैग के लिए कैसे किया जा सकता है। यह अत्यंत तेज है; मेरे पास गति पर चर्चा है कि PHP में सबसे तेज XML पार्सर क्या है?

टैग-आधारित पार्सिंग करते समय याद रखने वाली सबसे महत्वपूर्ण बात यह है कि इसका उपयोग किया जाए 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();
}

2
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));
    }
}

2

XMLReader PHP साइट पर अच्छी तरह से प्रलेखित है । यह एक XML Pull Parser है, जिसका अर्थ है कि यह दिए गए XML दस्तावेज़ के नोड्स (या DOM नोड्स) के माध्यम से पुनरावृति करने के लिए उपयोग किया जाता है। उदाहरण के लिए, आप इस तरह दिए गए पूरे दस्तावेज़ के माध्यम से जा सकते हैं:

<?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 द्वारा लौटाए गए नोड से कैसे निपटें :: विस्तार ()


इसे संसाधित करने के बाद आप इसे अगले नोड पर कैसे ले जाएंगे?
Shadi Almosri

24
इसके अलावा XMLReader के बारे में php.net पर अच्छी तरह से प्रलेखित होने से मैं असहमत होऊंगा, यह सबसे बुरे दस्तावेज में से एक है जिसे मैंने देखा है और मैंने लंबे समय तक php.net का उपयोग किया है और यह पहले स्थान पर था जिसने मुझे इसे हल करने के लिए नेतृत्व किया। यहाँ पूछ रहे हैं :)
Shadi Almosri

मुझे यकीन नहीं है कि आप XMLReader :: read () एक नोड से दूसरे में जाते हैं। XMLReader वर्ग libxml का उपयोग करता है, यह एक प्रसिद्ध पुस्तकालय है जो PHP के लिए भी उपलब्ध है यदि आप इसे देखना चाहते हैं।
पेरकटियो

12
XMLReader अच्छी तरह से प्रलेखित है यह विचार बकवास है। समस्या यह है कि यदि आप नहीं जानते हैं कि कहां से शुरू करना है, तो यह आपको कहीं भी नहीं बताता है: यदि आपके पास कॉल करने का पहला विचार नहीं है, तो कक्षा के तरीकों की कपड़े धोने की सूची देना बेकार है।
xgretsch

0

यह मेरे लिए बेहतर और तेज़ काम करता है


<html>
<head>
<script>
function showRSS(str) {
  if (str.length==0) {
    document.getElementById("rssOutput").innerHTML="";
    return;
  }
  if (window.XMLHttpRequest) {
    // code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
  } else {  // code for IE6, IE5
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function() {
    if (this.readyState==4 && this.status==200) {
      document.getElementById("rssOutput").innerHTML=this.responseText;
    }
  }
  xmlhttp.open("GET","getrss.php?q="+str,true);
  xmlhttp.send();
}
</script>
</head>
<body>

<form>
<select onchange="showRSS(this.value)">
<option value="">Select an RSS-feed:</option>
<option value="Google">Google News</option>
<option value="ZDN">ZDNet News</option>
<option value="job">Job</option>
</select>
</form>
<br>
<div id="rssOutput">RSS-feed will be listed here...</div>
</body>
</html> 

** बैकएंड फ़ाइल **


<?php
//get the q parameter from URL
$q=$_GET["q"];

//find out which feed was selected
if($q=="Google") {
  $xml=("http://news.google.com/news?ned=us&topic=h&output=rss");
} elseif($q=="ZDN") {
  $xml=("https://www.zdnet.com/news/rss.xml");
}elseif($q == "job"){
  $xml=("https://ngcareers.com/feed");
}

$xmlDoc = new DOMDocument();
$xmlDoc->load($xml);

//get elements from "<channel>"
$channel=$xmlDoc->getElementsByTagName('channel')->item(0);
$channel_title = $channel->getElementsByTagName('title')
->item(0)->childNodes->item(0)->nodeValue;
$channel_link = $channel->getElementsByTagName('link')
->item(0)->childNodes->item(0)->nodeValue;
$channel_desc = $channel->getElementsByTagName('description')
->item(0)->childNodes->item(0)->nodeValue;

//output elements from "<channel>"
echo("<p><a href='" . $channel_link
  . "'>" . $channel_title . "</a>");
echo("<br>");
echo($channel_desc . "</p>");

//get and output "<item>" elements
$x=$xmlDoc->getElementsByTagName('item');

$count = $x->length;

// print_r( $x->item(0)->getElementsByTagName('title')->item(0)->nodeValue);
// print_r( $x->item(0)->getElementsByTagName('link')->item(0)->nodeValue);
// print_r( $x->item(0)->getElementsByTagName('description')->item(0)->nodeValue);
// return;

for ($i=0; $i <= $count; $i++) {
  //Title
  $item_title = $x->item(0)->getElementsByTagName('title')->item(0)->nodeValue;
  //Link
  $item_link = $x->item(0)->getElementsByTagName('link')->item(0)->nodeValue;
  //Description
  $item_desc = $x->item(0)->getElementsByTagName('description')->item(0)->nodeValue;
  //Category
  $item_cat = $x->item(0)->getElementsByTagName('category')->item(0)->nodeValue;


  echo ("<p>Title: <a href='" . $item_link
  . "'>" . $item_title . "</a>");
  echo ("<br>");
  echo ("Desc: ".$item_desc);
   echo ("<br>");
  echo ("Category: ".$item_cat . "</p>");
}
?> 

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.