simplexml add child non attribute information - php

i'm trying to figure out how to add this right here;
<tech name="level 0" prereq="0" id="7" null="null">
<meta fuelx="1" energyx="1" cost="100" income="11">Description goes here</meta>
</tech>
to an already existing xml file.
I've gotten the first and the but I cannot figure out how to add the information between the &.

You can't add child nodes w/ SimpleXML. You can convert to DOM and then do it though.
$curNode = dom_import_simplexml($simpleXml);
$newChild = dom_import_simplexml($sXml);
$tmpNode = $curNode->ownerDocument->importNode($newChild, true);
$curNode->appendChild($tmpNode);
EDIT
Wow, it seems like they added an addChild method in 5.1.3, where have I been??

Related

php xml DOMDocument close tag element

I am using PHP DOMDocument() to generate XML file with elements.
I am appending all details into sample xml file into components tag. But closing tag is not coming. I want to create closing tag.
My Code is doing this
<component expiresOn="2022-12-31" id="pam" />
I want to do like following
<component expiresOn="2022-12-31" id="pam"></component>
My PHP CODE SAMPLE
$dom = new DOMDocument();
$dom->load("Config.xml");
$components = $dom->getElementsByTagName('components')->item(0);
if(!empty($_POST["pam"])) {
$pam = $_POST["pam"];
$component = $dom->createElement('component');
$component->setAttribute('expiresOn', $expirydate);
$component->setAttribute('id', "pam");
$components->appendChild($component5);
}
$dom->save("Config.xml");
I tested following suggestion and its not working. Both xml-php code are different.
$dom->saveXml($dom,LIBXML_NOEMPTYTAG);
Self-closing tags using createElement
I tested following.
You're trying to use DOMDocument::saveXML to save the new XML back into the original file, but all that function does is return the XML as a string. Since you aren't assigning the result to anything, nothing happens.
If you want to save the XML back to your file, as well as avoiding self-closing tags, you'll need to use the save method as you originally were, and also pass the option:
$dom->save('licenceConfig.xml', LIBXML_NOEMPTYTAG);
See https://3v4l.org/e6N5s for a demo

Manipulating XML with Dom

i'm trying to manipulate an xml by adding a few custom tags.
I managed to add a custom Element and a TextNode on it, but it gets rendered at the very bottom of the XML.
How do i add this custom tag as a child of another tag? i tried using the following code:
$product_record = $xml->documentElement->getElementsByTagName('product_record');
and then
$text = $test->appendChild($product_record);
But it doesn't seem to be working.
Here's where i got stuck:
http://viper-7.com/CsRNHU
How do i get the test tag to be rendered inside product_record?
Thanks,
Thales
Taking your full example you add the new element to the document itselt, not the fetched node.
The getElementsByTagName() method returns a list of nodes, not a single node, so you need to use a loop or fetch a specific element from the list.
$xml = new DOMDocument();
$xml->load($url);
$products = $xml->documentElement->getElementsByTagName('product_record');
foreach ($products as $product) {
$test = $product
->appendChild($xml->createElement('test'))
->appendChild($xml->createTextNode("testing"));
}
echo $xml->saveXML();
The DOMDocument::create*() methods create specific nodes and return them. The appendChild() method adds it to a parent node and returns the added node.
Your example returns an UTF-16 encoded XML. Import it into an UTF-8 XML document if you want to change the encoding:
$utf8 = new DOMDocument('1.0', 'UTF-8');
$utf8->appendChild($utf8->importNode($xml->documentElement, TRUE));
Demo: http://viper-7.com/1eCPeo

SimpleXML and PHP (XPATH)

Ok guys I'm using xml to store page information for a dynamic website. I need to figure out a way to take a variable(file name) and pull the related node and parse that information. so basically here's my XML structure...
<SITE>
<PAGE>
<FILENAME>sub.php</FILENAME>
<DESCRIPTION>this is an example sub page</DESCRIPTION>
<TITLE>NOH Sub page</TITLE>
<PARENTS>
<PARENT>What is NOH</PARENT>
</PARENTS>
</PAGE>
<PAGE>
<FILENAME>about.php</FILENAME>
<DESCRIPTION>description description description </DESCRIPTION>
<TITLE>About Us</TITLE>
<PARENTS>
<PARENT>Company</PARENT>
<PARENT>People</PARENT>
</PARENTS>
</PAGE>
</SITE>
Is there a way to use SimpleXML and PHP to take a variable say.. 'sub.php' and say I want the node where filename = 'sub.php', and then be able to parse that node(page) for needed info. Thanks!
Update, where I'm confused is...
i have this function
function getPage($pagePath){
$file = "includes/sitestructure.xml";
$xml = simplexml_load_file($file);
return print_r($xml-xpath(PAGE/FILENAME));
}
but my xpath doesn't work, and I'm not sure how to logically get the info I need.. I know how to normally parse XML with PHP but not how to specify a specific node by comparing it to a variable then parse it.
$xml-xpath(PAGE/FILENAME)
This is broken in several ways, but this is an XPath question not a PHP syntax one.
You want to get the PAGE element(s) which contain a FILENAME of your chosen file name. To do that in XPath, a predicate can be used.
PAGE[FILENAME="sub.php"]
In your PHP code that might look like
$pages = $xml->xpath('PAGE[FILENAME="sub.php"]');
$first_page = $pages[0];
echo $first_page->TITLE; // NOH Sub page
The important point here is the use of the predicate to filter the result to only the page element(s) that you want.
http://www.w3.org/TR/xpath/#predicates

How do I get the link element in a html page with PHP

First, I know that I can get the HTML of a webpage with:
file_get_contents($url);
What I am trying to do is get a specific link element in the page (found in the head).
e.g:
<link type="text/plain" rel="service" href="/service.txt" /> (the element could close with just >)
My question is: How can I get that specific element with the "rel" attribute equal to "service" so I can get the href?
My second question is: Should I also get the "base" element? Does it apply to the "link" element? I am trying to follow the standard.
Also, the html might have errors. I don't have control on how my users code there stuff.
Using PHP's DOMDocument, this should do it (untested):
$doc = new DOMDocument();
$doc->loadHTML($file);
$head = $doc->getElementsByTagName('head')->item(0);
$links = $head->getElementsByTagName("link");
foreach($links as $l) {
if($l->getAttribute("rel") == "service") {
echo $l->getAttribute("href");
}
}
You should get the Base element, but know how it works and its scope.
In truth, when I have to screen-scrape, I use phpquery. This is an older PHP port of jQuery... and what that may sound like something of a dumb concept, it is awesome for document traversal... and doesn't require well-formed XHTMl.
http://code.google.com/p/phpquery/
I'm working with Selenium under Java for Web-Application-Testing. It provides very nice features for document traversal using CSS-Selectors.
Have a look at How to use Selenium with PHP.
But this setup might be to complex for your needs if you only want to extract this one link.

How do I add new elements to XML using PHP DOM deeper than the root?

All of the examples I can find online about this involve simply adding content to an XML file at the document root, but I really need to do it deeper than that.
My XML file is simple, I have:
<?xml v1 etc>
<channel>
<screenshots>
<item>
<title>Image Title</title>
<link>www.link.com/image.jpg</link>
</item>
</screenshots>
</channel>
All I want to be able to do is add new "item" elements, each with a title and link. I know I need to be using PHP DOM, but I'm stumped as to how to code it so that it adds data within "screenshots" rather than overwriting the whole document. I have a suspicion I may need to use XPath too, but I have no idea how!
The code I have pieced together from online examples looks like this (but I'm certain it's wrong)
$newshottitle = "My new screenshot";
$newshotlink = "http://www.image.com/image.jpg";
$dom = newDomDocument;
$dom->formatOutput = true;
$dom->load("../xml/screenshots.xml");
$dom->getElementsByTagName("screenshots");
$t = $dom->createElement("item");
$t = $dom->createElement("title");
$t->appendChild($dom->createTextNode("$newshottitle"));
$l = $dom->createElement("link");
$l->appendChild($dom->createTextNode("$newshotlink"));
$dom->save("../xml/screenshots.xml");
adding content to an XML file at the document root, but I really need to do it deeper than that.
You're not adding content anywhere at the moment! You create <title> and <link> element nodes with text in, then you do nothing with them. You should be passing them into ‘appendChild’ on the <item> element node (which also you are currently creating and immediately throwing away by not assigning it to a variable).
Here's a starting-point:
$screenshots= $dom->getElementsByTagName("screenshots")[0];
$title= $dom->createElement("title");
$title->appendChild($dom->createTextNode($newshottitle));
$item= $dom->createElement("item");
$item->appendChild($title);
$screenshots->appendChild($item);

Categories