php simplexml find value of a specific field - php

The XML, I have:
<?xml version="1.0" encoding="windows-1252" ?>
- <Tables>
- <Table name="I_BOOKING">
- <Row action="UPDATE" success="Y">
<Field name="AUTOBOOK">888800</Field>
<Field name="TOUROP">01</Field>
<Field name="REFERENCE">GSDFFD</Field>
<Field name="NBPAX">2</Field>
<Field name="NBINF">1</Field>
</Row>
</Table>
- <Table name="I_EXCDATERESA">
- <Row action="UPDATE" success="Y">
<Field name="EXCURS">KNO</Field>
<Field name="DATE">2012-04-12</Field>
<Field name="BOOKNR">125445</Field>
<Field name="NAME">TEST 12/4</Field>
<Field name="PICKUPTIME">00:00:00</Field>
</Row>
- <Row action="UPDATE" success="Y">
<Field name="EXCURS">KNO</Field>
<Field name="DATE">2012-04-13</Field>
<Field name="BOOKNR">14574575</Field>
<Field name="NAME">TEST 13/4</Field>
<Field name="PICKUPTIME">00:00:00</Field>
</Row>
</Table>
</Tables>
When I treat the table I_EXCDATERESA, I need to get the value of Field BOOKNR, so 125445 or 14574575 in this example, according to the row I am dealing with and load it in $autobook:
...
$simplexml = simplexml_import_dom($dom);
foreach ($simplexml->Table as $value)
{
$tableName = $value->attributes()->name;
foreach ($value->Row as $value)
{
if ($tableName == 'I_EXCDATERESA')
{
if ($value->Field->attributes()->name == 'BOOKNR')
{
$autoBook = $value->Field;
This is not working, $autobook is not loaded, as it is not on the first 'Field' but on the third

This is a great use case for XPath:
$search = $simplexml->xpath('/Tables/Table[name="I_EXCDATERESA"]/Row/Field[name="BOOKNR"]');

Test this, it worked for me:
foreach ($simplexml->Table as $value)
{
$tableName = $value->attributes()->name;
foreach ($value->Row as $value_1)
{
if ($tableName == 'I_EXCDATERESA')
{
foreach ($value_1->Field as $value_2)
{
if ($value_2->attributes()->name == 'BOOKNR')
{
$autoBook = $value_2[0];
echo $autoBook;
}
}
}
}
}
Your problem is with:
$value->Field->attributes()->name=='BOOKNR'
That's too much: I added another cycle on each field of elemts Row!

well there are couple of ways to approach this situation
using DOM
using the attribute() function inside simplexml which was covered here
and probably the easiest option is noticing that BOOKNER is the third node in every Row
I would do something like this.
for ($i = 0; $i < count($simplexml->->children()); $i++){
echo $simplexml->Table[$i]->Table->Field[2];
}
good luck

$simplexml->xpath('/Tables/Table[name="I_EXCDATERESA"]/Row/Field[name="BOOKNR"]');
does'nt work, you missed the #
$simplexml->xpath('/Tables/Table[#name="I_EXCDATERESA"]/Row/Field[#name="BOOKNR"]');

Related

Accessing a specific XML element using xpath in PHP 7.x

Ok so I have some XML data.
$mydata = <<<XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE fmresultset PUBLIC "-//FMI//DTD fmresultset//EN" "https://HIDDEN:443/fmi/xml/fmresultset.dtd">
<fmresultset xmlns="http://www.filemaker.com/xml/fmresultset" version="1.0">
<resultset count="1" fetch-size="1">
<record mod-id="27" record-id="754">
<field name="a_Constant_c">
<data>1</data>
</field>
<field name="a_Sch_ID_pk">
<data>100060</data>
</field>
<field name="a_SchoolHead_pk">
<data>100060_1</data>
</field>
<field name="b___Data_____________">
<data/>
</field>
<field name="b_1Name_School_Code_t">
<data>PJA</data>
</field>
<field name="b_1Name_School_t">
<data>Palmetto</data>
</field>
<field name="b_1Name_SchoolHead_t">
<data>John Doe</data>
</field>
<field name="b_Ad_Address1_t">
<data/>
</field>
<field name="b_Ad_Address2_t">
<data>123 Main St.</data>
</record>
</resultset>
</fmresultset>
XML;
Now what I want to do is basically be able to read the value of the data from a specific field and assign it to a variable.
So far I have something like this...
$xml = simplexml_load_string($mydata);
Now I want to be able to assign let's say the data in the field name b_1Name_School_Code_t (which is PJA)
So I think it should be something like this
$school = $xml->resultset->record->field->data;
echo "School Name: ".$school;
Then I would like to see on the screen
School Name: PJA
So what I am missing to be able to make this happen?
You are only getting to the first field element in your example, which is why you get 1. Instead, loop through all the field elements, and stop when you get to the one you need:
$xml = simplexml_load_string($mydata);
$fields = $xml->resultset->record->field;
foreach ($fields as $field) {
if ((string) $field->attributes()->name === "b_1Name_School_Code_t") {
echo "School name: ".$field->data; // School name: PJA
break;
}
}
Demo
I use SimpleXMLElement::attributes() to get the name attribute of the element (note the cast to string, otherwise you get an SimpleXMLElement)
However, it would make more sense to use XPath to go directly to the element you're after:
$xml = simplexml_load_string($mydata);
$xml->registerXPathNamespace("fmresultset", "http://www.filemaker.com/xml/fmresultset");
$node = $xml->xpath("//fmresultset:resultset/fmresultset:record/fmresultset:field[#name='b_1Name_School_Code_t']");
var_dump($node[0]->data); // PJA
Demo
Notice the namespace registration and the accessing of the first element, since xpath() returns an array of SimpleXMLElements

How to insert dynamic row in different html table position

I want to echo following xml data in html table using php,
<type>Debit</type>
<item>Item-1</item>
<price>150</price>
<type>Debit</type>
<item>Item-2</item>
<price>250</price>
<type>Debit</type>
<item>Item-3</item>
<price>100</price>
type>Debit</type>
<item>Item-4</item>
<price>200</price>
............
...so on
<type>Credit</type>
<item>Item-50</item>
<price>200</price>
<type>Credit</type>
<item>Item-51</item>
<price>300</price>
<type>Credit</type>
<item>Item-60</item>
<price>100</price>
............
...so on
here is my Html table structure before inserting data
Now if you see my xml data, i want to dynamically insert debit items under Debit List and credit items in Credit List like the following sample:
I know how to add rows dynamically using insertRow(), getElementById("id").But in this case i need to maintain two different position [1 for debit, 1 for credit] so that i can insert them in correct position.Moreover rows are dynamic, so fixed id with fixed number of rows will not work i guess.How can i do this in php.Please share your idea to solve it in a vary simple way.Please let me know for any further information.Thanks
try this solution. If you use javascript, you use two tables and use append() element row in tbody.
<!DOCTYPE html>
<html>
<body>
<?php
$myXMLData =
"
<data>
<row>
<type>Debit</type>
<item>Item-1</item>
<price>150</price>
</row>
<row>
<type>Debit</type>
<item>Item-2</item>
<price>250</price>
</row>
<row>
<type>Debit</type>
<item>Item-3</item>
<price>100</price>
</row>
<row>
<type>Debit</type>
<item>Item-4</item>
<price>200</price>
</row>
<row>
<type>Credit</type>
<item>Item-50</item>
<price>200</price>
</row>
<row>
<type>Credit</type>
<item>Item-51</item>
<price>300</price>
</row>
<row>
<type>Credit</type>
<item>Item-60</item>
<price>100</price>
</row>
</data>";
$xml=simplexml_load_string($myXMLData) or die("Error: Cannot create object");
$debit = array();
$credit = array();
$debit_total = $credit_total = 0;
foreach ($xml as $row) {
if($row->type == 'Debit') {
$debit[] = array('item'=> (string)$row->item, 'price'=> (float)$row->price);
$debit_total += (float)$row->price;
} else {
$credit[] = array('item'=> (string)$row->item, 'price'=> (float)$row->price);
$credit_total += (float)$row->price;
}
}
?>
<table>
<tr>
<td colspan="2">Debit list<td>
</tr>
<?php
foreach ($debit as $key => $value) {
echo "<tr><td>{$value['item']}</td><td>{$value['price']}</td></tr>";
}
echo "<tr><td>Total</td><td>{$debit_total}</td></tr>";
echo "<tr><td colspan='2'></td></tr>";
echo "<tr><td colspan='2'>Credit list</td></tr>";
foreach ($credit as $key => $value) {
echo "<tr><td>{$value['item']}</td><td>{$value['price']}</td></tr>";
}
echo "<tr><td>Total</td><td>{$credit_total}</td></tr>";
echo "<tr><td colspan='2'></td></tr>";
?>
</table>
</body>
</html>

Getting multiple values with specific attributes in nested xml with php

I feel like this should be easy, but for the love of it I cannot get it right. I've read and tested for hours, trying different approaches I have found on the interwebs, both with simpleXML and PHP XML DOM, but none of them works just the way I need.
I got somewhat close, after tweaking and combining a few answers (that I cannot even find the way back to cause I've been through so many of them here), but not entirely correct.
My code:
$xml = simplexml_load_file(all_objects.xml");
$image = $xml->xpath('/objects/object/images/image');
foreach($image as $node) {
$id = (string) $node->field[0];
$url = (string) $node->field[4];
echo $id . " : " . $url . "<br>";
}
But instead of using the key/number they appear [4] in, I would like to target using the field name attribute, e.g. "id" and "image_url", as they are not always in this order.
Something like this:
$id = (string) $node->field["id"];
But it does not work, I tried with field->attribtues()->id too, but no luck.
The xml:
<objects>
<object>
<field name="id">1055</field>
<field name="title">example object</field>
<images>
<image number="1">
<field name="id">55</field>
<field name="version">1</field>
<field name="image_url_small">http://example.com/image-small.jpg</field>
<field name="image_url_medium">http://example.com/image-medium.jpg</field>
<field name="image_url_big">http://example.com/image-big.jpg</field>
<field name="image_url_original">http://example.com/image.jpg</field>
</image>
<image number="2">
<field name="id">56</field>
<field name="version">2</field>
<field name="image_url">http://example.com/image2.jpg</field>
</image>
<image number="3">...</image>
...
<image number="25">...</image>
</images>
</object>
<object>...</object>
<object>...</object>
</objects>
I would really appreciate any help/guidance! I am losing my mind over this.
You can use XPath to get child element with certain attribute value :
foreach($image as $node) {
$id = (string) $node->xpath('field[#name="id"]')[0];
$url = (string) $node->xpath('field[#name="image_url_big"]')[0];
echo $id . " : " . $url . "<br>";
}
eval.in demo
output :
55 : http://example.com/image-big.jpg
56 :
:
:

php xml parsing with attributes

I have some XML that looks like this
$xml_str = '<RESPONSE>
<FIELDS>
<FIELD KEY="A">1</FIELD>
<FIELD KEY="B">2</FIELD>
<FIELD KEY="C">3</FIELD>
<FIELD KEY="D">4</FIELD>
</FIELDS>
</RESPONSE>';
There is only ever going to be 1 "FIELDS" in the response. Is there a easy way I can put the "FIELD" elements in a array with the keys being the "KEY" and the value being the element value?
I could do this
$xml_data = simplexml_load_string($xml_str);
foreach ($xml_data->FIELDS->FIELD as $field) {
foreach ($field->attributes() as $a => $b) {
$array[$b] = $field[0];
}
}
But I'm wondering if there is a better way?
TIA

Select xml node by attribute in php [duplicate]

This question already has answers here:
SimpleXML: Selecting Elements Which Have A Certain Attribute Value
(2 answers)
Closed 2 years ago.
How do I find the node value by knowing the attribute value without traversing through every child and every attribute/value ?
$dom = new DOMDocument;
$dom->load('test.xml');
$rows = $dom->getElementsByTagName('row');
foreach ($rows as $row) {
$header = VALUE OF <field name="header">
$text = VALUE OF <field name="text">
}
XML:
<resultset>
<row>
<field name="item">2424</field>
<field name="header">blah blah 1</field>
<field name="text" xsi:nil="true" />
...
</row>
<row>
<field name="item">5321</field>
<field name="header">blah blah 2</field>
<field name="text">some text</field>
...
</row>
</resultset>
The simplest thing to do is use DOMXPath::querydocs
The following code finds all the <field> nodes within <row> nodes that have a name attribute equal to "header":
$dom = new DOMDocument;
$dom->loadXML($str); // where $str is a string containing your sample xml
$xpath = new DOMXPath($dom);
$query = "//row/field[#name='header']";
$elements = $xpath->query($query);
foreach ($elements as $field) {
echo $field->nodeValue, PHP_EOL;
}
Using the sample xml you provide, the above outputs:
blah blah 1
blah blah 2

Categories