I've currently got an XML file that's being imported using a plugin on WordPress.
I've got a field that's currently importing the data and time automatically, but the field contains data in the current format
<EndDate>2014-04-24T00:00:00+01:00</EndDate>
I need to remove the time field somehow, but I'm stuck on how to do this (using php).
Is there a way of creating a function to remove the time, so that the field pulls in;
<EndDate>YYYY-MM-DD</EndDate>
Please help.
You first need to exactly locate that field. You could use simplexml.
To output a formatted date you use the date function. It accepts a UNIX timestamp.
You obtain that timestamp by using the strtotime function, that takes a date+time formatted as a string and returns a UNIX timestamp.
Here is one way you can do what you are looking at
$xml = "<reservation>
<detail>
<name>XXXXX</name>
<EndDate>2014-04-24T00:00:00+01:00</EndDate>
</detail>
<detail>
<name>YYYYY</name>
<EndDate>2014-04-24T00:00:00+01:00</EndDate>
</detail>
</reservation>";
$data = simplexml_load_string($xml);
//rint_r($data);
foreach ($data->detail as $obj)
{
$end_date = $obj->EndDate ;
$date = new DateTime($end_date);
$obj->EndDate = $date->format("Y-m-d");
}
$new_xml = $data->asXML();
echo $new_xml ;
You can also save as file
$data->asXML($file);
I have used for loading the string as
$data = simplexml_load_string($xml);
You can load the file also as
$data = simplexml_load_file($file);
Xpath can be used so fetch nodes from the XML DOM, but it can extract scalar values, too. It has even some functions. One of them is string-before() that returns the part of a string before an substring.
$xml = "<EndDate>2014-04-24T00:00:00+01:00</EndDate>";
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
var_dump(
$xpath->evaluate('substring-before(//EndDate, "T")')
);
Output: https://eval.in/141939
string(10) "2014-04-24"
Related
I'm trying to parse an xml data that I'm getting via an api call. I can use file_get_contents to read into a string but simpleXML_load_string seems to fail to read it. I can save it to a file and then simpleXML_load_file works. But I would rather not write the contents to a file. I can't seem to understand how to use DOM or XMLParse with this either. I'm new to PHP and parsing XML. The output data from the api call is below.
<Search>
<DS_Rating>DS3</DS_Rating>
<Overall>17.5</Overall>
<LargestGiftLow>0</LargestGiftLow>
<LargestGiftHigh>0</LargestGiftHigh>
<EstimatedCapacityRange>I - $15,000 - $24,999</EstimatedCapacityRange>
<EstimatedCapacity>20452</EstimatedCapacity>
<RealEstateEst>270073</RealEstateEst>
<RealEstateCount>1</RealEstateCount>
<LikelyMatchesCount>0</LikelyMatchesCount>
<LikelyMatchesTotal>0</LikelyMatchesTotal>
<FndBoard></FndBoard>
<GSBoard></GSBoard>
<PoliticalLikelyCount>0</PoliticalLikelyCount>
<PoliticalLikelyTotal>0</PoliticalLikelyTotal>
<BusinessRevenues>0</BusinessRevenues>
<SECStockValue>0</SECStockValue>
<SECInsider></SECInsider>
<MarketGuide></MarketGuide>
<IRS990PF></IRS990PF>
<RealEstateTrust></RealEstateTrust>
<MarketGuideComp>0</MarketGuideComp>
<MarketGuideOptions>0</MarketGuideOptions>
<BusinessAffiliation></BusinessAffiliation>
<Pension></Pension>
<PensionAssets>0</PensionAssets>
<CorpTech></CorpTech>
<Pilot></Pilot>
<AirplaneOwner></AirplaneOwner>
<Boat></Boat>
<submit_time>2014-03-11 15:48:45</submit_time>
</Search>
Figured out that the issue was that what I was seeing in the browser was actually a php output with html_entiity encoded. I was able to process it with the code below which let me load it with simplexml.
$rawxml = html_entity_decode($rawxml);
$rawxml = str_replace(array(' ', "<pre>"), '', $rawxml);
$rawxml = utf8_encode($rawxml);
$xml = simplexml_load_string($rawxml);
If you XML is in a file use
simplexml_load_file
if you have it in a string use
simplexml_load_string
Then you can use the following code to access it.
<?php
$yourxml = simplexml_load_file('your.xml');
echo $yourxml->search[0]->DS_Rating;
?>
This would then output
DS3
to the browser via the 'echo' in your code. I hope this points you in the correct direction.
Try to use this:
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?>'.$yourXMLString);
In DOM you load the XML into a DOMDocument and create a DOMXpath instance for it.
$dom = new DOMDocument();
$dom->loadXml($xmlString);
//$dom->load($xmlFile);
$xpath = new DOMXpath($dom);
DOMXpath::evaluate() is used to fetch data from the DOM.
$rating = $dom->evaluate('string(/Search/DS_Rating)');
An Xpath expression like /Search/DS_rating always returns a node list. You can use foreach() to iterate it. The string() function in Xpath takes the first node from the list and casts it into a string. If here is not node in the list the result is an empty string.
$xmlString = <<<'XML'
<Search>
<DS_Rating>DS3</DS_Rating>
<Overall>17.5</Overall>
</Search>
XML;
$dom = new DOMDocument();
$dom->loadXml($xmlString);
$xpath = new DOMXpath($dom);
var_dump(
$xpath ->evaluate('string(/Search/DS_Rating)')
);
Output: https://eval.in/118921
string(3) "DS3"
I am using the PHP DOMDocument and at one moment I am using the createTextNode
$copyrightNode = $doc->createTextNode('©');
$copyrightContainer = $dom_output->createElement('copyright-statement');
$copyrightContainer->appendChild($copyrightNode);
In the XML that is generated some time later, I am getting:
<copyright-statement>©</copyright-statement>
And my goal is to have
<copyright-statement>©</copyright-statement>
Any idea on how to do that?
Thank you in advance.
When PHP outputs an XML document, any characters that cannot be represented in the specified output encoding will be replaced with numeric entities (either decimal or hexadecimal, both are equivalent):
<?php
$dom = new DOMDocument;
$node = $dom->createElement('copyright-statement', '©');
$dom->appendChild($node);
$dom->encoding = 'UTF-8';
print $dom->saveXML(); // <copyright-statement>©</copyright-statement>
$dom->encoding = 'ASCII';
print $dom->saveXML(); // <copyright-statement>©</copyright-statement>
The correct thing to do here is to use the createEntityReference method (e.g. createEntityReference("copy");), and then appendChild this entity.
Example:
<?php
$copyrightNode = $doc->createEntityReference("copy");
$copyrightContainer = $dom_output->createElement('copyright-statement');
$copyrightContainer->appendChild($copyrightNode);
To create © you could (I believe) do:
$copyrightNode = $doc->createCDATASection("©");
$copyrightContainer = $dom_output->createElement('copyright-statement');
$copyrightContainer->appendChild($copyrightNode);
I am trying to write a code where it will find a specific element in my XML file and then change the value of the text node. The XML file has different namespaces. Till now, I have managed to register the namespaces and also echo the text node of the element, which I want to change.
<?php
$xml = simplexml_load_file('getobs.xml');
$xml->registerXPathNamespace('g','http://www.opengis.net/gml');
$result = $xml->xpath('//g:beginPosition');
foreach ($result as $title) {
echo $title . "\n";
}
?>
My question is: How can I change the value of this element using SimpleXML? I tried to use the nodeValue command but I am not able to make it work.
This is a part of the XML:
<sos:GetObservation xmlns:sos="http://www.opengis.net/sos/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" service="SOS" version="1.0.0" srsName="urn:ogc:def:crs:EPSG:4326">
<sos:offering>urn:gfz:cawa:def:offering:meteorology</sos:offering>
<sos:eventTime>
<ogc:TM_During xmlns:ogc="http://www.opengis.net/ogc" xsi:type="ogc:BinaryTemporalOpType">
<ogc:PropertyName>urn:ogc:data:time:iso8601</ogc:PropertyName>
<gml:TimePeriod xmlns:gml="http://www.opengis.net/gml">
<gml:beginPosition>2011-02-10T01:10:00.000</gml:beginPosition>
Thanks
Dimitris
In the end I managed to do it by using the PHP XML DOM.
Here is the code that I used in order to change the text node of a specific element:
<?php
// create new DOM document and load the data
$dom = new DOMDocument;
$dom->load('getobs.xml');
//var_dump($dom);
// Create new xpath and register the namespace
$xpath = new DOMXPath($dom);
$xpath->registerNamespace('g','http://www.opengis.net/gml');
// query the result amd change the value to the new date
$result = $xpath->query("//g:beginPosition");
$result->item(0)->nodeValue = 'sds';
// save the values in a new xml
file_put_contents('test.xml',$dom->saveXML());
?>
Not wanting to switch from the code I've already made for SimpleXML, I found this solution:
http://www.dotdragnet.com/forum/index.php?topic=3979.0
Specificially:
$numvotes = $xml->xpath('/gallery/image[path="'.$_GET["image"].'"]/numvotes');
...
$numvotes[0][0] = $votes;
Hope this helps!
I was successfully using the following code to merge multiple large XML files into a new (larger) XML file. Found at least part of this on StackOverflow
$docList = new DOMDocument();
$root = $docList->createElement('documents');
$docList->appendChild($root);
$doc = new DOMDocument();
foreach(xmlFilenames as $xmlfilename) {
$doc->load($xmlfilename);
$xmlString = $doc->saveXML($doc->documentElement);
$xpath = new DOMXPath($doc);
$query = self::getQuery(); // this is the name of the ROOT element
$nodelist = $xpath->evaluate($query, $doc->documentElement);
if( $nodelist->length > 0 ) {
$node = $docList->importNode($nodelist->item(0), true);
$xmldownload = $docList->createElement('document');
if (self::getShowFileName())
$xmldownload->setAttribute("filename", $filename);
$xmldownload->appendChild($node);
$root->appendChild($xmldownload);
}
}
$newXMLFile = self::getNewXMLFile();
$docList->save($newXMLFile);
I started running into OUT OF MEMORY issues when the number of files grew as did the size of them.
I found an article here which explained the issue and recommended using XMLWriter
So, now trying to use PHP XMLWriter to merge multiple large XML files together into a new (larger) XML file. Later, I will execute xpath against the new file.
Code:
$xmlWriter = new XMLWriter();
$xmlWriter->openMemory();
$xmlWriter->openUri('mynewFile.xml');
$xmlWriter->setIndent(true);
$xmlWriter->startDocument('1.0', 'UTF-8');
$xmlWriter->startElement('documents');
$doc = new DOMDocument();
foreach($xmlfilenames as $xmlfilename)
{
$fileContents = file_get_contents($xmlfilename);
$xmlWriter->writeElement('document',$fileContents);
}
$xmlWriter->endElement();
$xmlWriter->endDocument();
$xmlWriter->flush();
Well, the resultant (new) xml file is no longer correct since elements are escaped - i.e.
<?xml version="1.0" encoding="UTF-8"?>
<CONFIRMOWNX>
<Confirm>
<LglVeh id="GLE">
<AddrLine1>GLEACHER & COMPANY</AddrLine1>
<AddrLine2>DESCAP DIVISION</AddrLine2>
Can anyone explain how to take the content from the XML file and write them properly to new file?
I'm burnt on this and I KNOW it'll be something simple I'm missing.
Thanks.
Robert
See, the problem is that XMLWriter::writeElement is intended to, well, write a complete XML element. That's why it automatically sanitize (replace & with &, for example) the contents of what's been passed to it as the second param.
One possible solution is to use XMLWriter::writeRaw method instead, as it writes the contents as is - without any sanitizing. Obviously it doesn't validate its inputs, but in your case it does not seem to be a problem (as you're working with already checked source).
Hmm, Not sure why it's converting it to HTML Characters, but you can decode it like so
htmlspecialchars_decode($data);
It converts special HTML entities back to characters.
I have a xml file like this
<?xml version="1.0" encoding="UTF-8"?>
<gallery >
<gallerydata>
<galleryname>
Home
</galleryname>
<createdat>
14/8/2010 4:53 pm
</createdat>
</gallerydata>
<gallerydata>
<galleryname>
School
</galleryname>
<createdat>
13/8/2010 5:19 pm
</createdat>
</gallerydata>
<gallerydata>
<galleryname>
Company
</galleryname>
<createdat>
15/8/2010 5:21 pm
</createdat>
</gallerydata>
</gallery>
Iam using xpath and xquery for parsing this xml file
$xml_str = file_get_contents($file);
$xml = simplexml_load_string($xml_str);
$nodes = $xml->xpath('//gallery/gallerydata');
How i can get the latest gallery data, i mean latest file (the data with last date )
Is their any way to do ?Please help me
IF you looking for a way to do it with the initial xpath query that could be rough, i dont think xpath 1.0 can parse dates so youd have to do some convoluted string comparison... If youre ok with doing it in php after the fact theres a multitude of ways... for example:
$xml = new SimpleXmlElement($xmlStr);
$gallerydata = $xml->xpath('//gallerydata');
$nodes = array();
foreach($gallerydata as $entry)
{
$utime = strtotime(str_replace('/', '-',$entry->createdat));
$nodes[$utime] = $entry;
}
krsort($nodes);
$newest = array_shift($nodes);
echo $newest->asXml(); // or do wht you need to do with the entry data...
This loops over your renturned node set and puts the nodes in an array indexed by unix time. Then I run a reversed key sort and shift the first element off the array. Note, that since im using strtotime for the conversion and you have UK date formats we have to do a string replace on the slashes.
Since your file does not store gallery data in chronological order, you can get the latest gallery entry only by looping through all the entries.