Navigating XML documents in PHP using OTA standards

While I have a basic understanding of utilizing Xpath in PHP, I am currently facing difficulties with a specific scenario. Initially, I suspect that the issue lies within the standards.

The following XML snippet adheres to the OTA standards:

<SendHotelResResult xmlns:a="http://schemas/Models/OTA" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <a:RoomRates>
         <a:RoomRate>
             <a:EffectiveDate>2015-11-13T00:00:00</a:EffectiveDate>
             <a:ExpireDate>2015-11-15T00:00:00</a:ExpireDate>
             <a:RatePlanID>25</a:RatePlanID>
             <a:RatesType>
                 <a:Rates>
                     <a:Rate>
                         <a:AgeQualifyingCode i:nil="true"/>
                                 <a:EffectiveDate>2015-11-13T00:00:00</a:EffectiveDate>
                         <a:Total>
                             <a:AmountAfterTax>0</a:AmountAfterTax>
                             <a:AmountBeforeTax>260.00</a:AmountBeforeTax>
                             <a:CurrencyCode>EUR</a:CurrencyCode>
                          </a:Total>
                     </a:Rate>
                     <a:Rate>
                         <a:AgeQualifyingCode i:nil="true"/>
                             <a:EffectiveDate>2015-11-14T00:00:00</a:EffectiveDate>
                         <a:Total>
                             <a:AmountAfterTax>0</a:AmountAfterTax>
                             <a:AmountBeforeTax>260.00</a:AmountBeforeTax>
                             <a:CurrencyCode>EUR</a:CurrencyCode>
                         </a:Total>
                     </a:Rate>
                 </a:Rates>
             </a:RatesType>
             <a:RoomID>52</a:RoomID>
             <a:Total>
                 <a:AmountAfterTax>546.00</a:AmountAfterTax>
                 <a:AmountBeforeTax>520.00</a:AmountBeforeTax>
                 <a:CurrencyCode>EUR</a:CurrencyCode>
             </a:Total>
         </a:RoomRate>
     </a:RoomRates>
</SendHotelRes>

Desired Outcome:

  1. To retrieve a specific <RoomRate> tag based on the element <RoomID>.
  2. To attain the global RoomRate <Total> tag excluding the one nested inside the <Rate> tag. This is why Xpath is preferred over getElementsByTagName('Total'). The concern here is whether the OTA standards include a distinct approach to distinguish between Total tags.

My current attempts:

$dom = new DOMDocument();
$response = $dom->load($xmlSendHotelRes);
$roomID = '52';
$roomRatesTag = $response->getElementsByTagName('RoomRates')->item(0);
$prefix = $roomRatesTag->prefix;
$namespace = $roomRatesTag->lookupNamespaceURI($prefix);
$xpath = new DOMXpath($dom);
$xpath->registerNamespace($prefix, $namespace);
$roomRateTotal = $xpath->query("//RoomRate[RoomID=$roomID]/Total", $roomRatesTag, true);

I have experimented with and without $roomRatesTag as context along with other expressions like: ./RoomRate[RoomID=$roomID]/Total, //RoomRate[RoomID=$roomID]/Total,

//RoomRate/[RoomID=$roomID]/Total
,//RoomRate[RoomID=$roomID]/Total and
//RoomRate/RoomID[text() = $roomID]/../Total
, but none seem to yield results.

In fact, even

$roomRate = $xpath->query("//RoomRate");
returns an empty DOMNodeList, leaving me perplexed about my errors. Considering the presence of 2 identical tags in different locations, I'm contemplating if this relates to issues with the standards despite its improbability.

Could there be alternative expressions worth exploring?

Answer №1

Retrieving the namespace from the document is a common practice.

$prefix = $roomRatesTag->prefix;
$namespace = $roomRatesTag->lookupNamespaceURI($prefix);

However, in this case, it may not be necessary or advisable. Since the document utilizes OTA, we are aware that the namespace is http://schemas/Models/OTA.

The prefix serves as an alias for the actual namespace value, as demonstrated by the following 3 XML examples all pointing to the node

{http://schemas/Models/OTA}RoomRates

  • <a:RoomRates xmlns:a="http://schemas/Models/OTA"/>
  • <ota:RoomRates xmlns:ota="http://schemas/Models/OTA"/>
  • <RoomRates xmlns="http://schemas/Models/OTA"/>

When accessing nodes within the namespace through your API, there are multiple approaches you can take.

One option involves utilizing the *NS (namespace aware) methods.

$response->getElementsByTagNameNS('http://schemas/Models/OTA', 'RoomRates')->item(0);

Alternatively, you can employ Xpath and establish prefixes for the namespaces, whether they mirror those in the document or differ.

$document = new DOMDocument();
$document->load($xmlSendHotelRes);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('ota', 'http://schemas/Models/OTA');

var_dump(
  $xpath->evaluate(
    'string(//ota:RoomRates/ota:RoomRate[ota:RoomID=$roomID]/ota:Total)')
  )
);

When using a location path, DOMXpath::evaluate() typically returns a DOMNodeList; however, with string(), it converts the first discovered node into a string before returning it.

Answer №2

To correctly search relative to the context node, it is important to use a registered prefix and begin your path with .// instead of just //. For example, you can try using

".//a:RoomRate[a:RoomID=$roomID]/a:Total"

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The driver encounters an issue with finding elements when there is an empty bar present in the bar chart

I am working on automating and extracting information from a graph based on the tooltip displayed on hover action. The XPath for the SVG area covering the bars is: //div[contains(@class,'commonGraphStyle__CommonGraphStyle')][3]//*[local-name()=& ...

Issue occurred: The error "Undefined offset 1" was encountered while trying to upload a file via

Every time I try to pass data into my file upload controller, I keep encountering an error message that says undefined offset: 1. function TestFileUpload() { $i=0; if(!isset($_FILES[$i]) ) { echo "No file is being uploaded"; } el ...

The style attribute encountered issues while using the writeHTML function in the tcpdf class

Can we apply a style attribute to an HTML tag while writing to a PDF file using TCPDF's writeHTML method? See the code snippet below: $html = "<div style=\"font-size: 20px; border: solid blue; float: left; margin: 10px 25px 25px 100px;">PR ...

Taking data input from three textboxes and storing them in a PHP array

In my HTML form, I have 3 text input fields and one submit button. Each text field is intended for entering the name of an animal, which should then be saved into a PHP array. Here is the structure of my HTML form: <form action="Test.php" method="post ...

Prevent form submission once all tasks have been finalized

Hey there, I've been racking my brain for hours trying to solve this issue... I'm looking to disable my form after it's been submitted to prevent multiple submissions. However, every method I try seems to disable the button but also interfe ...

Looking for a way to redirect a subdomain URL to the non-www version? Let me help you with the ht

My domain is example.com and I have set up a redirect code in the .htaccess file to direct traffic to various URLs including https://www.example.com/, , and https://www.example.com/test/ RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https:/ ...

Creating a visually appealing background image using WordPress and PHP

Currently struggling with adjusting the width of an image that's set as a background in Wordpress. The text is perfectly centered, but the background image remains full size and I want it to match the container size... You can view the image at the t ...

PHP: Retrieving the current time zone from the database

In my database, I save dates in DATETIME format as Y-m-d H:i:s. My goal is to display the date from the database in the user's local time. For instance, if the user is located in France, I want to show their timezone. Is there a way to accomplish thi ...

Upon loading the webpage, I aim to display an alert containing the information retrieved from a row in the database table

I would like to check if the current system date matches the date in my database table. If there is a match, I want to display the corresponding member's name in an alert when the page loads. Here is My Code: <?php $now = date("Y/m/d"); ...

Addressing Layout Problems When I Enlarge the Browser Width

My website is www.adventureswithross.com When the device width is larger than 601px, I have specific requirements: I need the menu and custom header to be seamlessly connected without any spacing in between. To address the issue of space above the custo ...

Mastering the Art: Efficiently Breaking Down Laravel 5.2's Query Builder!

I have three variables that I need to check before adding a specific where clause. If these variables are not null or blank, the where clauses should be added. $brand = $request->brand == 0 ? "" : $request->brand ; $category = $request->category ...

"Improving the efficiency of text preprocessing for text mining in PHP can help exped

As I work on text preprocessing for text mining with a large database, I am facing challenges in creating an array of article data from the database due to the slow processing time. $multiMem = memory_get_usage(); $xstart = microtime(TRUE); $word = ""; ...

Transferring the selected option from a drop-down menu to a PHP page using an HTML form

I'm currently working on developing an HTML form that will send the user's question and the selected topic to a PHP page. The topics are retrieved from a MySQL database using PHP. My goal is to submit the chosen topic value from a dropdown menu, ...

What is the best way to send an array from ajax to php?

I'm having an issue passing an array from AJAX to PHP (controller). What could be the issue with the second block of code given that var_dump($data) in the first block returns the expected content while in the second it returns NULL? FIRST. GOOD. f ...

Having difficulty combining the two Middlewares into a group

Currently, I'm working on integrating three different user types into my application using Laravel's default Auth system. To accomplish this, I've created two extra middlewares for the additional user conditions (admin & Districtlogin) alon ...

Store the content of an HTML div using HTML5 Drag and Drop functionality in a MYSQL database

Here's a simple scenario: I have 3 small divs (1, 2, 3) and I want to place them inside 3 other divs (4, 5, 6). That's no issue, but then I need to store the data in MySQL, such as 4-1, 5-2, 6-3 for instance. I can use JavaScript to display the n ...

Using PHP's strtotime function with multiple variables

I have the following PHP code snippet: $timestamp2 = strtotime('13:30 04/12/2013'); However, I would like to include these variables in the code: $mi = mysql_real_escape_string($_POST['mi']); $ho = mysql_real_escape_s ...

Is there a way to define a varying number of OR conditions in a Doctrine SQL Where clause?

Is there a way to dynamically generate a Doctrine ORM query that mimics the following SQL statement, considering that the number of values in the 'OR' clause may vary with each execution? SELECT * FROM table1 WHERE table1.group = 1 OR 2 OR ...

The combination of Google App Engine with Google Drive API leads to an ERROR:root:php failure (255) occurring

Currently, my PHP setup (using Zend Framework 2) is functioning well with proper exception handling. However, I am encountering a peculiar issue when interacting with the Google Drive API through the Google PHP library. Whenever this API is called, my appl ...

What is the best way to dynamically change the JSON-LD Script for the Schema?

Below is the script in question. Please read through it carefully. <script type="application/ld+json"> { "@context": "http://schema.org/", "@type": "Product", "name": "Bat, &q ...