Import XML with attributes into mysql - php

I have a large (~30Mb) XML file like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<LIC Version="2.0" Title="Products">
<Item>
<Field Name="Filename">/root/_DOWNLOAD/Bird.txt</Field>
<Field Name="Read_By">Lisa Hannigan</Field>
<Field Name="Posit">Passenger</Field>
</Item>
<Item>
<Field Name="Filename">D:\03\Strypers.pdf</Field>
<Field Name="Read_By">Stryper</Field>
<Field Name="Intensity">2</Field>
<Field Name="IMG">78</Field>
<Field Name="Rotate">0</Field>
</Item>
<Item>
<Field Name="Filename">D:\Afriu.txt</Field>
<Field Name="Read_By">Africano</Field>
<Field Name="Posit">Canto Africano vol.1</Field>
<Field Name="File_Resource">mp3</Field>
</Item>
<Item>
<Field Name="Filename">D:\_VARIOUS\Knots.pdf</Field>
<Field Name="Date">40624</Field>
</Item>
...
</LIC>
I want to import this xml into mysql database, with a php script. I've used SIMPLEXML and xpath:
$url = 'FILE.xml';
$xml = simplexml_load_file($url);
$result = $xml->xpath("//Field[#Name]");
foreach { ... }
What do i need? What is the correct "foreach" to create an array to use for mysql sql?
Notes that every row (identify by "Item") is not same (not have the same "Field Name").
Is it correct to use simplexml for larger file?
Thank you for help!
update
This is an example to use "foreach", i tried:
$result = $xml->xpath("//Field[#Name]");
foreach($result as $key => $value) {
echo $value['Name']."=".$value.",";
}
Now I want to find out how to create the string to insert in mysql

First create a table that matches all possible fields as columns. Then you can load it by a LOAD XML LOCAL INFILE query.
LOAD XML LOCAL INFILE 'file.xml'
INTO TABLE person
ROWS IDENTIFIED BY '<Item>';

I try to answer my question.
<?php
$url = 'FILEXML';
$xml = simplexml_load_file($url);
$i = 1;
foreach($xml->xpath("/LIC/Item") as $docs)
{
foreach($docs->Field as $field)
{
$resultstr[] = $field["Name"];
}
$sql_head = headquote($resultstr);
$sql_ins = "INSERT INTO table_name (";
$sql_dec = ") VALUE (";
unset($resultstr);
$fresult = (array)$docs;
$fvalue = array_pop($fresult);
$sql_val = numking($fvalue);
$sql_end = ");";
$query_to_use_for_mysql = ($sql_ins.$sql_head.$sql_dec.$sql_val.$sql_end);
unset($fresult);
unset($fvalue);
}
?>
And add this two functions:
<?php
function headquote($hdarray) {
$hdata = array();
foreach ( $hdarray as $hdval ) {
# Use backticks instead quotes!
$hdata[] = "`$hdval`";
}
$hdarray = implode($hdata, ',');
return $hdarray;
}
function numking($input) {
$data = array();
foreach ( $input as $value ) {
$data[] = is_numeric($value) ? $value : "'".mysql_escape_string($value)."'";
}
$input = implode($data, ',');
return $input;
}
?>
Thanks to all for help!

$url = 'FILE.xml';
$xml = simplexml_load_file($url);
for($i=0;$i<count($xml->Item);$i++)
{
print_r($xml->Item[$i]);
}

Related

How to get 2 child ID value from XML?

I wanted to try to pick up Volume value from the Level1Data node.
Here is the xml:
<Response>
<Content>
<Level1Data Tick="U" Currency="USD" TickSize="0.0001000000" TickValue="0" AssetClass="Equity" InstrumentState="Open" LastPrice="24.1550" LotSize="10"
MinPermittedPrice="0" MaxPermittedPrice="0" ClosePrice="24.0300" OpenPrice="24.1500" FirstPrice="24.1500"
HighPrice="24.7800" LowPrice="24.0000" MaxPrice="24.7800" MinPrice="24.0000" Volume="16238302"
AskSize="105597" BidSize="97618" AskPrice="24.1600" BidPrice="24.1500" Symbol="BAC.NY"
MarketTime="12:08:41.356" Message="L1DB"/>
</Content>
</Response>
And then my main script:
<?php
$result = file_get_contents("lvl1.xml");
// echo $result;
$xml = new SimpleXMLElement($result);
// $dom = new DOMDocument();
// $dom->loadXML("lvl1.xml");
// $vol = dom->getElementsByTagName('Level1Data');
$vol=$xml->children->children('Level1Data');
$id = $xml["Volume"];
echo $id;
?>
Nothing gets returned and I am having a hard time reading the php documentation and their examples.
Thank you.
You can try to find the XML node using attributes() and foreach what attribute you want as per your requirements. If you need only single attribute then discard foreach looping.
<?php
$result =<<<EOT
<Response>
<Content>
<Level1Data Tick="U" Currency="USD" TickSize="0.0001000000" TickValue="0" AssetClass="Equity" InstrumentState="Open" LastPrice="24.1550" LotSize="10"
MinPermittedPrice="0" MaxPermittedPrice="0" ClosePrice="24.0300" OpenPrice="24.1500" FirstPrice="24.1500"
HighPrice="24.7800" LowPrice="24.0000" MaxPrice="24.7800" MinPrice="24.0000" Volume="16238302"
AskSize="105597" BidSize="97618" AskPrice="24.1600" BidPrice="24.1500" Symbol="BAC.NY"
MarketTime="12:08:41.356" Message="L1DB"/>
</Content>
</Response>
EOT;
$volume = '';
$xml = new SimpleXMLElement($result);
foreach($xml->Content->Level1Data[0]->attributes() as $a => $b) {
if($a=='Volume'){
$volume = $b;
}
}
echo $volume;
?>
Demo https://eval.in/839942
OR for single attribute e.g Volume
echo $xml->Content->Level1Data[0]->attributes()->Volume;
If you want to pickup Volume only, it can also be done as follows.
<?php
$result = <<<EOM
<Response>
<Content>
<Level1Data Tick="U" Currency="USD" TickSize="0.0001000000" TickValue="0" AssetClass="Equity" InstrumentState="Open" LastPrice="24.1550" LotSize="10"
MinPermittedPrice="0" MaxPermittedPrice="0" ClosePrice="24.0300" OpenPrice="24.1500" FirstPrice="24.1500"
HighPrice="24.7800" LowPrice="24.0000" MaxPrice="24.7800" MinPrice="24.0000" Volume="16238302"
AskSize="105597" BidSize="97618" AskPrice="24.1600" BidPrice="24.1500" Symbol="BAC.NY"
MarketTime="12:08:41.356" Message="L1DB"/>
</Content>
</Response>
EOM;
$xml = new SimpleXMLElement($result);
echo $xml->Content->Level1Data[0]->attributes()->Volume;
EDIT
<?php
$result = <<<EOM
<Response>
<Content>
<Level1Data Tick="U" Currency="USD" TickSize="0.0001000000" TickValue="0" AssetClass="Equity" InstrumentState="Open" LastPrice="24.1550" LotSize="10"
MinPermittedPrice="0" MaxPermittedPrice="0" ClosePrice="24.0300" OpenPrice="24.1500" FirstPrice="24.1500"
HighPrice="24.7800" LowPrice="24.0000" MaxPrice="24.7800" MinPrice="24.0000" Volume="16238302"
AskSize="105597" BidSize="97618" AskPrice="24.1600" BidPrice="24.1500" Symbol="BAC.NY"
MarketTime="12:08:41.356" Message="L1DB"/>
</Content>
</Response>
EOM;
$xml = new SimpleXMLElement($result);
function recur($obj){
if ( in_array('Level1Data', array_keys( (array) $obj->children()) ) === false){
recur($obj->children());
}else{
var_dump($obj->children()->Level1Data);
exit;
}
}
recur($xml);

foreach shows attributes of first xml node only

I am trying to display attributes foreach global_ivr_variable:
$xml = '
<response method="switchvox.ivr.globalVariables.getList">
<result>
<global_ivr_variables>
<global_ivr_variable id="1" name="cid_name" value="Smith" />
<global_ivr_variable id="2" name="Q_ID_Global" value="COS" />
</global_ivr_variables>
</result>
</response>
';
$sxml = simplexml_load_string($xml);
foreach($sxml->result->global_ivr_variables->global_ivr_variable->attributes() as $a => $b)
{
echo $a .'=' . $b . "<br>";
}
All I get is the attributes of the first node:
id="1"
name="cid_name"
value="Smith"
I've also tried the following, which gives me no values at all...
foreach($sxml->result->global_ivr_variables as $xvar)
{
$a = $xvar->global_ivr_variable->id;
$b = $xvar->global_ivr_variable->name;
$c = $xvar->global_ivr_variable->value;
echo 'a='.$a.', b='.$b.', c='.$c.'<br>';
}
a=, b=, c=
Thank you all who step up to help the needy!
You almost had it but you need to iterate through each of the <global_ivr_variable> elements and then pull out the attributes:
foreach($sxml->result->global_ivr_variables->global_ivr_variable as $variable)
{
foreach($variable->attributes() as $a => $b)
{
echo $a .'=' . $b . "<br>";
}
}
If you make use of PHP variables, those problems normally easily disappear because your code is more readable.
Additionally you can access the attributes in SimpleXML via array-notation:
$variables = $sxml->result->global_ivr_variables->global_ivr_variable;
foreach ($variables as $variable)
{
printf("%s = %s\n", $variable['name'], $variable['value']);
}
This gives the following output:
cid_name = Smith
Q_ID_Global = COS
As you know upfront for which attributes you're looking for, your code is much more clear and stable by using those names.
However, if you're looking for just all attributes of the global_ivr_variable elements, then it's easier to iterate over them with XPath:
$allAttributes = $sxml->xpath('//global_ivr_variable/#*');
foreach ($allAttributes as $attribute) {
printf("%s = %s\n", $attribute->getName(), $attribute);
}
This then gives the following output:
id = 1
name = cid_name
value = Smith
id = 2
name = Q_ID_Global
value = COS
Here is the full code-example:
$xml = <<<XML
<response method="switchvox.ivr.globalVariables.getList">
<result>
<global_ivr_variables>
<global_ivr_variable id="1" name="cid_name" value="Smith" />
<global_ivr_variable id="2" name="Q_ID_Global" value="COS" />
</global_ivr_variables>
</result>
</response>
XML;
$sxml = simplexml_load_string($xml);
$variables = $sxml->result->global_ivr_variables->global_ivr_variable;
foreach ($variables as $variable)
{
printf("%s = %s\n", $variable['name'], $variable['value']);
}
echo "----\n";
$allAttributes = $sxml->xpath('//global_ivr_variable/#*');
foreach ($allAttributes as $attribute) {
printf("%s = %s\n", $attribute->getName(), $attribute);
}

Get data from an xml file

In a php script how to read and convert a XML document to an object and access the obtained object in order to get his data?
<?php
$xml ='<?xml version="1.0" encoding="UTF-8" ?>
<data request-id="ID">
<data name="Name1"
d1="0"
d2="0231234"
d3="32584">
<data name="Name2"
d4="231234"
d5="2012-06-06 18:18:10.000607"
d6="3b048653-aaa9-485b-b0dd-d16e068230e9" />
</data>
</data>';
$xml = simplexml_load_string($xml);
//how to get the data d1? or d4? from the obtained object
?>
You can use this snippet:
<?php
$xmlstring = file_get_contents($filename);
$xml = simplexml_load_string($xmlstring);
$json = json_encode($xml);
$object = json_decode($json);
Try using this function -
$xml ='<?xml version="1.0" encoding="UTF-8" ?>
<data request-id="ID">
<data name="Name1"
d1="0"
d2="0231234"
d3="32584">
<data name="Name2"
d4="231234"
d5="2012-06-06 18:18:10.000607"
d6="3b048653-aaa9-485b-b0dd-d16e068230e9" />
</data>
</data>';
function xmlToArray($input, $callback = null, $recurse = false) {
$data = ((!$recurse) && is_string($input))? simplexml_load_string($input, 'SimpleXMLElement', LIBXML_NOCDATA): $input;
if ($data instanceof SimpleXMLElement) $data = (array) $data;
if (is_array($data)) foreach ($data as &$item) $item = xmlToArray($item, $callback, true);
return (!is_array($data) && is_callable($callback))? call_user_func($callback, $data): $data;
}
$xml = xmlToArray($xml);
echo $xml['data']['#attributes']['d1'];
echo '<br/>';
echo $xml['data']['data']['#attributes']['d4'];
Use
$myxml = simplexml_load_string($xml);
echo $myxml->data[1]['d1'];
echo $myxml->data[1]['d2'];
echo $myxml->data[1]['d3'];
echo $myxml->data[2]['d4'];
Reference : How to parse XML with PHP5
try :-
echo $xml['data']['#attributes']['d1'];
echo '<br/>';
echo $xml['data']['data']['#attributes']['d4'];

Get next element with PHP SimpleXML

I received a very weird XML file to process.
Instead of grouping names with group tags, like this:
<data>
<group>
<name>John</name>
<name>Mary</name>
<name>Susan</name>
</group>
<group>
<name>Cesar</name>
<name>Joseph</name>
<name>Sylvia</name>
<name>Steve</name>
</group>
</data>
It inserts a separator tag after each element, like this:
<data>
<name>John</name>
<separator>,</separator>
<name>Mary</name>
<separator>,</separator>
<name>Susan</name>
<separator>;</separator>
<name>Cesar</name>
<separator>,</separator>
<name>Joseph</name>
<separator>,</separator>
<name>Sylvia</name>
<separator>,</separator>
<name>Steve</name>
<separator>.</separator>
</data>
";" and "." are the group delimiters. (I know, that's weird, but I can't change that and I have to process a lot of these files)
To get all names and all separators I can use the following code:
$data = <<<XML
<data>
<name>John</name>
<separator>,</separator>
<name>Mary</name>
<separator>,</separator>
<name>Susan</name>
<separator>;</separator>
<name>Cesar</name>
<separator>,</separator>
<name>Joseph</name>
<separator>,</separator>
<name>Sylvia</name>
<separator>,</separator>
<name>Steve</name>
<separator>.</separator>
</data>
XML;
$xml = simplexml_load_string($data);
foreach ($xml->name as $name){
echo "$name\n";
}
foreach ($xml->separator as $sep){
echo "$sep\n";
}
But this way, I can't get the name and the correspondent separator on a single loop.
Is there any way to know, on the first loop, the next element of each name?
I hope that i understand your question.
$xml = simplexml_load_string($data);
$i = 0;
$res = '';
foreach ($xml->name as $name){
$res .= "$name ".$xml->separator[$i];
$i++;
}
$groups = explode(';',$res);
Parse the XML like this and build an array:
$xml = simplexml_load_string($x);
foreach ($xml->children() as $name => $value) {
if ($name == 'name') $names[$i][] = (string)$value;
elseif ($name == 'separator' && $value == ';') $i++;
}
Output $names:
array(2) {
[0]=>array(3) {
[0]=>string(4) "John"
[1]=>string(4) "Mary"
[2]=>string(5) "Susan"
}
[1]=>array(4) {
[0]=>string(5) "Cesar"
[1]=>string(6) "Joseph"
[2]=>string(6) "Sylvia"
[3]=>string(5) "Steve"
}
}
You can then just pick the names from the array.
see it working: https://eval.in/95853

Can I use SQL syntax on SimpleXML?

Can I use a WHERE selector (like SQL syntax) on SimpleXML?
Example XML
<?xml version="1.0" encoding="utf-8" ?>
<documentElement>
<row>
<id>1</id>
<name>David</name>
<surname>Johnson</surname>
</row>
<row>
<id>2</id>
<name>Jack</name>
<surname>Nixon</surname>
</row>
</documentElement>
My Example Where Selector
$where = "Jack";
$xml = "example.xml";
$sxml = simplexml_load_string($xml);
foreach ($sxml->row as $data=>$row)
{
if ($where == $data->name) // some code here
else // other some code here
}
Please let me know.
Thank you.
Yes, there is a way: XPath
$where = "Jack";
$xml = "example.xml";
$sxml = simplexml_load_string($xml);
var_dump($sxml->xpath('/documentElement/row/name[.="'.$where.'"]/..'));
No, but you can do this:
$where = "Jack";
$xml = "example.xml";
$sxml = simplexml_load_string($xml);
foreach ($sxml->row as $row)
{
if ($row->name == $where) {
// ...
} else {
// other some code here
}
}

Categories