I have a XML file which looks like this:
<?xml version="1.0" encoding="utf-8"?>
<data>
<config>
</config>
<galleries>
// We have loads of these <gallery>
<gallery>
<name>Name_Here</name>
<filepath>filepath/file.txt</filepath>
<thumb>filepath/thumb.png</thumb>
</gallery>
</galleries>
</data>
I have been trying to figure out how to append another < gallery > to my above xml file. I tried using simplexml but couldn't get it to work, so I tried this answer as well as a bunch of others on stackoverflow. But just cant get it to work.
I can read from a xml file easily and get all the info I need, But I need to be able to append a gallery tag to it, The code below doesnt work and when it does, I can only insert 1 element, and it inserts it 3 times, i dont understand this.
$data = 'xml/config.xml';
// Load document
$xml = new DOMDocument;
$xml->load( $data ); #load data into the element
$xpath = new DOMXPath($xml);
$results = $xpath->query('/data/galleries');
$gallery_node = $results->item(0);
$name_node = $xml->createElement('name');
$name_text = $xml->createTextNode('nametext');
$name_node = $name_node->appendChild($name_text);
$gallery_node->appendChild($name_node);
echo $xml->save($data);
I've had loads of failed attempts at this, this should be so easy. Basically I want to add a gallery with childs name filepath and thumb to this same file (xml/config.php).
Like I said, I kinda got it to work, but its unformatted and a doesnt have the gallery tag.
Question
How do I insert another < gallery > (with children) into the above XML file?
Preferably even using simpleXML
With SimpleXML, you can use the addChild() method.
$file = 'xml/config.xml';
$xml = simplexml_load_file($file);
$galleries = $xml->galleries;
$gallery = $galleries->addChild('gallery');
$gallery->addChild('name', 'a gallery');
$gallery->addChild('filepath', 'path/to/gallery');
$gallery->addChild('thumb', 'mythumb.jpg');
$xml->asXML($file);
Be aware that SimpleXML will not "format" the XML for you, however going from an unformatted SimpleXML representation to neatly indented XML is not a complicated step and is covered in lots of questions here.
Related
I have a script that reads XML node by node using XMLReader:
$z = new XMLReader;
$z->open('xmlfile.xml');
$doc = new DOMDocument;
while ($z->read() && $z->name !== 'item');
while ($z->name === 'item')
{
$node = simplexml_import_dom($doc->importNode($z->expand(), true));
//I read the node here
print_r($node);
//Here I want to delete it
//////////////////////////
//move to next node
$z->next('item');
}
I want to delete the node from XML file after reading it to avoid reading same data multiple times when calling the script again. What is the best way to do it? Am I able to do it while reading the file?
I couldn't find the answer anywhere else.
XMLReader has a partner called XMLWriter. So for large XML files you read the XML file using XMLReader while writing the filtered/modified data using XMLWriter into a new file.
Expanding a part of the file into DOM allows easier reading and modifications of this part but you will need to use XMLWriter to serialize the XML structure into the new file.
I implemented features (including a collapse() method) for that into FluentDOM. Here is an usage example:
$xml = <<<'XML'
<persons>
<person><name>Alice</name></person>
<person><name>Bob</name></person>
<person><name>Charlie</name></person>
</persons>
XML;
// Create the target writer and add the root element
$writer = new \FluentDOM\XMLWriter();
$writer->openUri('php://stdout');
$writer->setIndent(2);
$writer->startDocument();
$writer->startElement('persons');
// load the source into a reader
$reader = new \FluentDOM\XMLReader();
$reader->open('data://text/plain;base64,'.base64_encode($xml));
// iterate the person elements - the iterator expands them into a DOM element node
foreach (new \FluentDOM\XMLReader\SiblingIterator($reader, 'person') as $person) {
/** #var \FluentDOM\DOM\Element $person */
// ignore "Bob"
if ($person('string(name)') !== 'Bob') {
// write expanded node to the output
$writer->collapse($person);
}
}
$writer->endElement();
$writer->endDocument();
Output:
<?xml version="1.0"?>
<persons>
<person>
<name>Alice</name>
</person>
<person>
<name>Charlie</name>
</person>
</persons>
You can't edit the document while reading it .. at least not without a lot of messy inefficient code.
Best approach would be:
1) Read the entire document into a second DOMDocument object.
2) As you read nodes one by one from your XMLReader input stream, find the corresponding nodes in the DOMDocument and remove them after you are done. Be careful not to delete nodes that have children you have not yet reviewed.
3) When done save the new DomDocument to a new file name and use this as your input source for next edit session.
You will be an expert on DomDocument manipulation when you are done.
Post a new question if you run into problems.
I am beginner in PHP, XSLT. Found solution for transform XML using XSLT:
$xml = Array2XML::createXML('Document', $result);
$xsl = new DOMDocument;
$xsl->load('Teema.xsl');
$processor = new XSLTProcessor();
$processor->importStyleSheet($xsl);
$results=$processor->transformToXML($xml);
$results=$processor->transformToUri($xml,"NewTeema.xml" );
But, what to do if I have 2 or more XMLs?
This $xml is not file, and I dont want to save each xml, like file on server (because it is was converted response json). Any ideas?
In the XSLT you can load additional document using the document() function.
Another possibility is to register a PHP function that loads the file and returns the value or DOM node.
Good solution, but I decided to merge 2 json, like this:
json_encode(array_merge(json_decode($result,
true),json_decode($resultProducts, true)));
And the use = Array2XML::createXML('Document', $result);
I am very new to XSL. I need to process the same XML file with 2 XSL files using PHP SimpleXML. I have tried a few different approaches with no luck.
$xmlfile = 'media/xml_files/article.xml';
if (file_exists($xmlfile)) {
$xml = simplexml_load_file($xmlfile) or die("Error: Cannot create object");}
$xslfile = media/xsl_files/jats-html.xsl;
$xsl = simplexml_load_file($xslfile);
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
echo $proc->transformToXML($xml);
I need to process the XML with jats-PMCcit.xsl before it goes through the jats-html.xsl transform. Can somebody please point me in the right direction? I can't seem to find an answer online anywhere.
You can try using XSLTProcessor::transformToDoc() to process the first transformation and get intermediate transformation result in a DOMDocument object type. Then you can pass the DOMDocument object to transformToXML() to get the final transformation result.
I'm currently trying to create a VLC playlist with PHP. This works pretty well with SimpleXML, but on one point I'm stuck.
A VLC Playlist needs a starting tag like:
<?xml version="1.0" encoding="UTF-8"?>
But Simple XML is always creating a xml tag around the whole element, which will look like
<xml>
<tag></tag>
</xml>
But what i need is:
<?xml version="1.0" encoding="UTF-8"?>
<playlist xmlns="[...]" xmlns:vlc="[...]" version="1">
<title>Test<title>
<trackList>
[...]
</trackList>
</playlist>
How can i create a xml file like this with simpleXML?
You miss some specifics about XML which drives you into wrong assumptions. Let's shed some light:
A VLC Playlist needs a starting tag like:
<?xml version="1.0" encoding="UTF-8"?>
This is wrong in many ways. First of all this is not a starting tag. This is the so called XML Declaration. So it is not a starting tag but something different.
Second, VLC does not require this. The XML Declaration is optional so it is for VLC.
But Simple XML is always creating a xml tag around the whole element, which will look like
No, Simple XML is handling this fine. It does not create a xml tag around the whole element. What you did do actually was wrong, resulting into the wrong results. But that is not SimpleXML's fault in this case but your fault (you have not shared the code, so excuse the generalization I do here).
Then you ask how to create some XML file with SimpleXML. With the (little) information you've shared, it goes like this:
$playlist = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><playlist xmlns="uri:1" xmlns:vlc="uri:2" version="1"/>');
$playlist->title = 'Test';
$playlist->trackList = "[...]";
$playlist->asXML('php://output');
Output then is:
<?xml version="1.0" encoding="utf-8"?>
<playlist xmlns="uri:1" xmlns:vlc="uri:2" version="1"><title>Test</title><trackList>[...]</trackList></playlist>
If you want it pretty-printed, see here: PHP simpleXML how to save the file in a formatted way?
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><playlist></playlist>');
$trackList = $xml->addChild('trackList');
foreach ($_POST['files'] as $video) {
$track = $trackList->addChild('track');
$track->addChild('location', 'file://'.$tmp_dir.'/'.$video['path']);
$track->addChild('title', $video['name']);
}
file_put_contents('playlist.xspf',$xml->asXML());
I have an xml document that is generated based on what the parametres are in the URL
for example:
menu.php?category=clothing
This will generate an xml page.
Now I want to display this in a formatted way on the menu, after having a look it seems that:
file_get_contents() seems to be the best option.
But I was just wondering how I can place elements and attributes found in this xml into the html code?
Any tips/help would be hugely appreciated!
One way to do it is to use PHP's SimpleXML:
Tutorial on SimpleXML
Simple load as a string or a file:
$source = 'mydata.xml';
// load as string
$xmlstr = file_get_contents($source);
$parseXML = new SimpleXMLElement($xmlstr);
print($parseXML);
// load as file
$parseXMLFile = new SimpleXMLElement($source,null,true);
print_r($parseXMLFile);
Let's say this is your xml file:
<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
<title>PHP: Behind the Parser</title>
</movie>
</movies>
Doing this would give you the title:
$parseXMLFile = new SimpleXMLElement($source,null,true);
echo $parseXMLFile->movie[0]->title;