0
\$\begingroup\$

I have stored in a XML file some Travel packages, each package has a code( the codes are stored in an array = $code).

I am using the below code to pull the requested data from the XML based on the given code. At this time I have copy/paste the code for each given code, but I have lots more and I dont want to copy paste code over and over

How can I simplify the below code so I don't have to paste it for all code that I have?

 <?php
 $code = array("BAS12", "BAS12", "BAS13", "BAS14");
 $dom = new DOMDocument();
 $xpath = new DOMXPath($dom);
 $reader = new XMLReader();
 $reader->open("file.xml");
 while ($reader->read()) {
 if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'Hotel') {
 $node = $dom->importNode($reader->expand(), true);
 $dom->appendChild($node);
 $nume1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/HotelName)', $node);
 $tara1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/Country)', $node);
 $oras1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/City)', $node);
 $adresa1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/Adress)', $node);
 $stele1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/Stars)', $node);
 $masa1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/TipMasa)', $node);
 $camera1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/TipCamera)', $node);
 $pret1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/Pret)', $node);
 $descriere1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/Descriere)', $node);
 $persoane1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/Persoane)', $node);
 $img1 = $xpath->evaluate('string(self::Hotel[HotelCode = "'.$code[0].'"]/Imagine1)', $node);
 $dom->removeChild($node);
 if ($nume1) {
 break; }
 if ($tara1) {
 break; } 
 if ($oras1) {
 break; }
 if ($adresa1) {
 break; } 
 if ($stele1) {
 break; }
 if ($camera1) {
 break; } 
 if ($masa1) {
 break; } 
 if ($pret1) {
 break; } 
 if ($persoane1) {
 break; } 
 if ($img1) {
 break; }
 }
 }
 ?>
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Feb 12, 2015 at 12:20
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Why don't you read the code into a variable and check if it is in the array of codes? After that fill up an array with the results.

Nearly every time you have a variable with a counter in the name, you should use arrays.

Another optimization is using XMLReader::next() to go directly to the next sibling without reading the child nodes.

You don't need to append the imported node, you need to provide it as a context in the DOMXpath::evaluate() calls anyway.

$codes = ["BAS11", "BAS12", "BAS13", "BAS14"];
$hotels = [];
$dom = new DOMDocument();
$xpath = new DOMXPath($dom);
$reader = new XMLReader();
$reader->open($filename);
// look for the first Hotel element (include descendants)
while ($reader->read() && $reader->localName !== 'Hotel') {
 continue;
}
// while you have an Hotel element
while ($reader->localName === 'Hotel') {
 // no need to append the node to the document, just import it
 $node = $dom->importNode($reader->expand(), true);
 // read the HotelCode
 $code = $xpath->evaluate('normalize-space(./HotelCode)', $node);
 // if it is in the list
 if (in_array($code, $codes)) {
 // read the values
 $hotels[$code] = [
 'name' => $xpath->evaluate('string(./HotelName)', $node),
 'country' => $xpath->evaluate('string(./Country)', $node),
 //...
 ];
 }
 // move directly to the next Hotel sibling
 $reader->next('Hotel'); 
}
var_dump($hotels);
answered Feb 12, 2015 at 14:39
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.