I've been tearing my hair out with this now for a few hours and thought I'd post it up here to see if anybody had any suggestions.
Basically I am receving some XML date via SOAP/Curl call which looks like this:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<LocationAvailabilityResponse xmlns="">
<getAvailabilityReturn>
<errors />
<requestID>389851</requestID>
<hotels>
<hotels>
<hotel>
<apt>false</apt>
<distance>0</distance>
<fromPrice>18.5</fromPrice>
<hotelName>Britannia Hotel Stockport</hotelName>
<id>5165</id>
<images>
<images>
<hasThumbnail>true</hasThumbnail>
<height>187</height>
<thumbnailHeight>50</thumbnailHeight>
<thumbnailURL>http://static.superbreak.net/content/images/Hotel/thumbs/britannia_hotel_stockport_swimming_pool_1_swi_5165.JPG</thumbnailURL>
<thumbnailWidth>68</thumbnailWidth>
<title>Britannia Hotel Stockport</title>
<url>http://static.superbreak.net/content/images/Hotel/britannia_hotel_stockport_swimming_pool_1_swi_5165.JPG</url>
<width>257</width>
</images>
<images>
<hasThumbnail>false</hasThumbnail>
<height>187</height>
<thumbnailHeight>0</thumbnailHeight>
<thumbnailURL>http://static.superbreak.net/content/images/Hotel/thumbs/britannia_hotel_stockport_swimming_pool_2_swi_5165.JPG</thumbnailURL>
<thumbnailWidth>0</thumbnailWidth>
<title>Swimming Pool</title>
<url>http://static.superbreak.net/content/images/Hotel/britannia_hotel_stockport_swimming_pool_2_swi_5165.JPG</url>
<width>257</width>
</images>
<images>
<hasThumbnail>false</hasThumbnail>
<height>187</height>
<thumbnailHeight>0</thumbnailHeight>
<thumbnailURL>http://static.superbreak.net/content/images/Hotel/thumbs/britannia_hotel_stockport_hotel_entrance_1_ent_5165.JPG</thumbnailURL>
<thumbnailWidth>0</thumbnailWidth>
<title>Hotel Entrance</title>
<url>http://static.superbreak.net/content/images/Hotel/britannia_hotel_stockport_hotel_entrance_1_ent_5165.JPG</url>
<width>257</width>
</images>
<images>
<hasThumbnail>false</hasThumbnail>
<height>187</height>
<thumbnailHeight>0</thumbnailHeight>
<thumbnailURL>http://static.superbreak.net/content/images/Hotel/thumbs/britannia_hotel_stockport_hotel_gym_1_gym_5165.JPG</thumbnailURL>
<thumbnailWidth>0</thumbnailWidth>
<title>Hotel Gym</title>
<url>http://static.superbreak.net/content/images/Hotel/britannia_hotel_stockport_hotel_gym_1_gym_5165.JPG</url>
<width>257</width>
</images>
<images>
<hasThumbnail>false</hasThumbnail>
<height>187</height>
<thumbnailHeight>0</thumbnailHeight>
<thumbnailURL>http://static.superbreak.net/content/images/Hotel/thumbs/britannia_hotel_stockport_hotel_lounge_1_lou_5165.JPG</thumbnailURL>
<thumbnailWidth>0</thumbnailWidth>
<title>Hotel Lounge</title>
<url>http://static.superbreak.net/content/images/Hotel/britannia_hotel_stockport_hotel_lounge_1_lou_5165.JPG</url>
<width>257</width>
</images>
<images>
<hasThumbnail>false</hasThumbnail>
<height>187</height>
<thumbnailHeight>0</thumbnailHeight>
<thumbnailURL>http://static.superbreak.net/content/images/Hotel/thumbs/britannia_hotel_stockport_four_poster_bedroom_1_pst_5165.JPG</thumbnailURL>
<thumbnailWidth>0</thumbnailWidth>
<title>Four Poster Bedroom</title>
<url>http://static.superbreak.net/content/images/Hotel/britannia_hotel_stockport_four_poster_bedroom_1_pst_5165.JPG</url>
<width>257</width>
</images>
</images>
<latitude>53.398941</latitude>
<location>Stockport</location>
<longitude>-2.13463</longitude>
<starRating>3</starRating>
</hotel>
<roomUnits>
<roomUnits>
<allocation>1</allocation>
<boardCode>RO</boardCode>
<boardDescription>Room only</boardDescription>
<maxOccupancy>2</maxOccupancy>
<minOccupancy>1</minOccupancy>
<price>18.5</price>
<stdOccupancy>2</stdOccupancy>
<unitDescription>Double For 1-2</unitDescription>
<unitID>162</unitID>
</roomUnits>
<roomUnits>
<allocation>1</allocation>
<boardCode>RO</boardCode>
<boardDescription>Room only</boardDescription>
<maxOccupancy>2</maxOccupancy>
<minOccupancy>1</minOccupancy>
<price>18.5</price>
<stdOccupancy>2</stdOccupancy>
<unitDescription>Twin For 1-2</unitDescription>
<unitID>161</unitID>
</roomUnits>
<roomUnits>
<allocation>1</allocation>
<boardCode>RO</boardCode>
<boardDescription>Room only</boardDescription>
<maxOccupancy>2</maxOccupancy>
<minOccupancy>2</minOccupancy>
<price>23.5</price>
<stdOccupancy>2</stdOccupancy>
<unitDescription>Executive Double Room</unitDescription>
<unitID>65</unitID>
</roomUnits>
<roomUnits>
<allocation>1</allocation>
<boardCode>RO</boardCode>
<boardDescription>Room only</boardDescription>
<maxOccupancy>2</maxOccupancy>
<minOccupancy>2</minOccupancy>
<price>23.5</price>
<stdOccupancy>2</stdOccupancy>
<unitDescription>Executive Twin Room</unitDescription>
<unitID>64</unitID>
</roomUnits>
</roomUnits>
</hotels>
I'm attempting to iterate through each hotels hotels result and turn each result into a multi dimensional array. The code I'm using which isn't working as I'd like is below:
$doc = new DOMDocument();
if ($doc->loadXML($result)) {
$items = $doc->getElementsByTagName('hotels');
$hotelnames = array();
foreach($items as $item) {
$hotelname = array();
$hotelimages = array();
if($item->childNodes->length) {
foreach($item->childNodes as $i) {
$hotelname[$i->nodeName] = $i->nodeValue;
if($i->childNodes->length){
foreach($i->childNodes as $z) {
if($z->childNodes->length){
foreach($z->childNodes as $x) {
$hotelimage[$x->nodeName] = $x->nodeValue;
}
}
}
}
$hotelimages[] = $hotelimage;
}
}
$hotelnames[] = $hotelname;
}
}
I'm guessing the issues I'm facing are mostly caused by the fact that the child and parent nodes are named the same for hotels and for the images.
Any help or a nod in the right direction will be much appreciated.
I suggest you using xpath (for example in SimpleXML implementation http://php.net/manual/en/simplexmlelement.xpath.php) for loading the values you need.
Or if you need whole XML parsed to array, you can always use PEAR XML_Serializer package (http://pear.php.net/package/XML_Serializer) to unserialize your XML.
Instead of working directly with the DOM I would recommend that you, unless you actually do need access to the DOM, perform these tasks using SimpleXML
It makes it very easy to work with XML data and you can act on it almost like a normal array.
Example
<?php
$url = 'http://www.flickr.com/services/feeds/photos_public.gne';
foreach(simplexml_load_file($url)->entry as $entry) {
echo $entry->content;
}
?>
Quite few lines for that functionality :)
Good luck!
I am looking in to the XML and I noticed some XML tags are not correct
Ex: <images><images></images><images></images></images> same is the case with roomunit.
I think it should be like <images><image></image><image></image></images> this will help to iterate over XML tag in php.
Related
I am having nested XML, I want to remove only parent node < items> in xml document keeping all its child nodes.
<root>
<items>
<Product>
<name> </name>
<size> </size>
<images>
<img1></img1>
<img2></img2>
</images>
</Product>
<Product>
<name> </name>
<size> </size>
<images>
<img1></img1>
<img2></img2>
</images>
</Product>
</items>
</root>
Expected Output -
<root>
<Product>
<name> </name>
<size> </size>
<images>
<img1></img1>
<img2></img2>
</images>
</Product>
<Product>
<name> </name>
<size> </size>
<images>
<img1></img1>
<img2></img2>
</images>
</Product>
</root>
I have researched & tried a lot, on removing the < items> node all its child nodes are also getting deleted. Please help if there is any way using DOMDocument or any other way in php.
Well, Geza Boems answer is not exactly what I meant. Using Xpath you can fetch the items nodes for iteration. This is a stable result, so you can iterate it while modifying the DOM.
$document = new DOMDocument();
$document->loadXML($input);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('//items') as $itemsNode) {
// as long that here is any child inside it
while ($itemsNode->firstChild instanceof DOMNode) {
// move it before its parent
$itemsNode->parentNode->insertBefore($itemsNode->firstChild, $itemsNode);
}
// remove the empty items node
$itemsNode->parentNode->removeChild($itemsNode);
}
echo $document->saveXML();
As #ThW mentioned, you have to collect the child nodes in ITEMS, then insert them into ROOT, and finally delete ITEMS.
$input = "
<root>
<items>
<Product>
<name> </name>
<size> </size>
<images>
<img1></img1>
<img2></img2>
</images>
</Product>
<Product>
<name> </name>
<size> </size>
<images>
<img1></img1>
<img2></img2>
</images>
</Product>
</items>
</root>";
$doc = new DOMDocument();
$ret = $doc->loadXML($input);
$root = $doc->firstChild;
$nodes_to_insert = array();
$nodes_to_remove = array();
foreach($root->childNodes as $items) {
if($items->nodeName != "items") {
continue;
}
$nodes_to_remove[] = $items;
foreach($items->childNodes as $child) {
if($child->nodeType != XML_ELEMENT_NODE) {
continue;
}
$nodes_to_insert[] = $child;
}
}
foreach($nodes_to_insert as $node) {
$root->appendChild($node);
}
foreach($nodes_to_remove as $node) {
$root->removeChild($node);
}
var_dump($doc->saveXML());
This code will search for all "items" tag within root, not only one. Inside "items", it will search all normal node (ELEMENT type, but no TEXT node, etc.)
In the last line there is a dump, but normally you will not see anything in a browser, because of the XML header line. But if you take a look at page source, the result will be shown.
PS: it is quite important to not modify xml structure when you walk it. That's why i do only collection first, then the insert and delete actions.
I'm trying to combine multiple XML files, using SimpleXML if possible. I'm just trying to append products, children, and child data from file 2 into file 1. I'm not trying to merge elements, just append file 2 to the bottom of file 1, and so on. (Though I guess this is technically merging merchandiser elements?) The files contain the same schema and will both look similar to the example below, only thing that will be changing is the actual text. This is just XML for two different products, I added a large space in between products so that it's easier to see where it ends.
<merchandiser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="merchandiser.xsd">
<header>
<merchantId>35928</merchantId>
<merchantName>Sunspel Clothing</merchantName>
<createdOn>01/14/2016 02:03:31</createdOn>
</header>
<product product_id="14633" name="Cotton Socks" sku_number="1588/102">
<category>
<primary>Accessories</primary>
<secondary>Men's~~Socks</secondary>
</category>
<URL>
<product>
http://click.linksynergy.com/link?id=D*rqD2paIXY&offerid=191965.14633&type=15&murl=http%3A%2F%2Fwww.sunspel.com%2Fuk%2Fcotton-sock-black.html
</product>
<productImage>
http://www.sunspel.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/1/5/1588-102-new.jpg
</productImage>
</URL>
<description>
<short>
Our new cotton socks are designed by Sunspel and crafted in an Italian factory steeped in years of experience, skill and heritage. They are made from the highest quality, extra-long staple Egyptian cotton yarn which, prior to knitting is combed, twisted and mercerised to enhance the comfort, shine and absorption of the fabric as well as its resistance to pilling and shrinking.
</short>
</description>
<discount currency="GBP">
<type>amount</type>
</discount>
<price currency="GBP">
<retail>15.00</retail>
</price>
<shipping>
<availability>in-stock</availability>
</shipping>
<pixel>
http://ad.linksynergy.com/fs-bin/show?id=D*rqD2paIXY&bids=191965.14633&type=15&subid=0
</pixel>
</product>
<product product_id="15115" name="Cotton Socks" sku_number="1589/236">
<category>
<primary>Accessories</primary>
<secondary>Men's~~Socks~~Men's</secondary>
</category>
<URL>
<product>
http://click.linksynergy.com/link?id=D*rqD2paIXY&offerid=191965.15115&type=15&murl=http%3A%2F%2Fwww.sunspel.com%2Fuk%2Fmens-cotton-socks-navy-stripes.html
</product>
<productImage>
http://www.sunspel.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/1/5/1588-236-new.jpg
</productImage>
</URL>
<description>
<short>
Our new cotton socks are designed by Sunspel and crafted in an Italian factory steeped in years of experience, skill and heritage. They are made from the highest quality, extra-long staple Egyptian cotton yarn which, prior to knitting is combed, twisted and mercerised to enhance the comfort, shine and absorption of the fabric as well as its resistance to pilling and shrinking.
</short>
</description>
<discount currency="GBP">
<type>amount</type>
</discount>
<price currency="GBP">
<retail>17.00</retail>
</price>
<shipping>
<availability>in-stock</availability>
</shipping>
<pixel>
http://ad.linksynergy.com/fs-bin/show?id=D*rqD2paIXY&bids=191965.15115&type=15&subid=0
</pixel>
</product>
<product product_id="15116" name="Cotton Socks" sku_number="1589/711">
<category>
<primary>Accessories</primary>
<secondary>Men's~~Socks~~Men's</secondary>
</category>
<URL>
<product>
http://click.linksynergy.com/link?id=D*rqD2paIXY&offerid=191965.15116&type=15&murl=http%3A%2F%2Fwww.sunspel.com%2Fuk%2Fmens-cotton-socks-charcoal-melange-stripes.html
</product>
<productImage>
http://www.sunspel.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/1/5/1588-711-new.jpg
</productImage>
</URL>
<description>
<short>
Our new cotton socks are designed by Sunspel and crafted in an Italian factory steeped in years of experience, skill and heritage. They are made from the highest quality, extra-long staple Egyptian cotton yarn which, prior to knitting is combed, twisted and mercerised to enhance the comfort, shine and absorption of the fabric as well as its resistance to pilling and shrinking.
</short>
</description>
<discount currency="GBP">
<type>amount</type>
</discount>
<price currency="GBP">
<retail>17.00</retail>
</price>
<shipping>
<availability>in-stock</availability>
</shipping>
<pixel>
http://ad.linksynergy.com/fs-bin/show?id=D*rqD2paIXY&bids=191965.15116&type=15&subid=0
</pixel>
</product>
With some foreach statements I'm able to append all product children and attributes, but this doesn't actually give me the child data.
$file1 = '35928_3210820_mp.xml';
$file2 = '39153_3210820_mp.xml';
$fileout = 'ukmerge.xml';
$xml1 = simplexml_load_file( $file1 );
$xml2 = simplexml_load_file( $file2 ); // loop through the product and add them and their attributes to xml1
$product = $xml2->product;
$prod = $xml2->merchandiser->header->product;
$category = $product->category;
$url = $product->URL;
$description = $product->description;
foreach( $xml2->children() as $child ) {
$new = $xml1->addChild( $child->getName() , htmlspecialchars($child) );
foreach( $child->attributes() as $key => $value ) {
$new->addAttribute( $key, $value );
}
} $fh = fopen( $fileout, 'w') or die ( "can't open file $fileout" );
fwrite( $fh, $xml1->asXML() );
fclose( $fh );
When I try to add on from there then everything gets messed up and nothing is in the correct place/order anymore. I'd also like to put this into a function since I'm going to be doing it often. Any help is greatly appreciate as I've been struggling with this for a few days now and have scowered over a few dozen stackoverflow and php.net threads.
One of the things that's confusing me is the <merchandiser> and <header> tags that every file starts with. Once the merchandiser tag ends it is the end of the document so I need to take only what's inside the merchandiser tag of file 2 and append it inside the merchandiser tag of file 1. The header tag just confuses me cause I'm not sure if it's gets in the way or not.
As preliminary note, your XML sample is malformed. Also it is not coherent with your code (i.e. there is not ->merchandiser->header->product ).
So, in this example I will use a different sample, like this one (file1.xml):
<root>
<product>
<name>Product 1</name>
</product>
<product>
<name>Product 2</name>
</product>
</root>
and this one (file2.xml):
<root>
<product>
<name>Product 3</name>
</product>
<product>
<name>Product 4</name>
</product>
</root>
You don't want to use DOMDocument->importNode() due “it kept throwing a lot of errors”.
You can use DOMDocument in conjunction with SimpleXML and dom_import_simplexml() function.
First of all, prepare destination XML: load the file with SimpleXML, create a DOMDocument using dom_import_simplexml() and set $parent variable to <root> element:
$dst = simplexml_load_file( 'file1.xml' );
$dst = dom_import_simplexml( $dst )->ownerDocument;
$parent = $dst->getElementsByTagName( 'root' )->item(0);
Then, load second file with SimpleXML:
$src = simplexml_load_file( 'file2.xml' );
Through a foreach() loop, import each <product> element from SimpleXML to DOMDocument and appent it as child of $parent node:
foreach( $src->product as $product )
{
$node = dom_import_simplexml( $product );
$node = $dst->importNode( $node, 1 );
$parent->appendChild( $node );
}
Now, your merged XML is ready. You can print it using $dst->saveXML().
I've not be able to product a correctly indented XML. BTW to do this, you can reload-it:
$final = new DOMDocument();
$final->loadXML( $dst->saveXML(), LIBXML_NOBLANKS );
$final->formatOutput = True;
echo $final->saveXML();
Final output:
<?xml version="1.0"?>
<root>
<product>
<name>Product 1</name>
</product>
<product>
<name>Product 2</name>
</product>
<product>
<name>Product 3</name>
</product>
<product>
<name>Product 4</name>
</product>
</root>
I am having some issues using xmldiff package. I'm using xmldiff package 0.9.2; PHP 5.4.17; Apache 2.2.25.
For example I have two xml files: "from.xml" & "to.xml".
File "from.xml" contains:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<rott>
<NDC>321</NDC>
<NDC>123</NDC>
</rott>
</root>
File "to.xml" contains:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<rott>
<NDC>123</NDC>
<NDC>321</NDC>
</rott>
</root>
I'm using code:
$zxo = new XMLDiff\File;
$dir1 = dirname(__FILE__) . "/upload/from.xml";
$dir2 = dirname(__FILE__) . "/upload/to.xml";
$diff = $zxo->diff($dir1, $dir2);
$file = 'differences.xml';
file_put_contents($file, $diff);
I get result in "differences.xml" file:
<?xml version="1.0"?>
<dm:diff xmlns:dm="http://www.locus.cz/diffmark">
<root>
<rott>
<dm:delete>
<NDC/>
</dm:delete>
<dm:copy count="1"/>
<dm:insert>
<NDC>321</NDC>
</dm:insert>
</rott>
</root>
</dm:diff>
Could you please comment from where this:
<dm:delete>
<NDC/>
</dm:delete>
comes?
Also please kindly inform me if there is a method which differs two xml files without matter of xml nodes order?
What you see is the diff in the libdiffmark format. Right from that page:
<copy/> is used in places where the input subtrees are the same
The documents from your snippet have partially identical sub trees. Effectively the instructions libdiffmark will execute are
delete the whole subtree
copy 1 nodes, that means the node is the same in the both documents, so don't touch it
insert 1 new node
The order of the nodes matters. Please think about how a diff would look like, if the node order were ignored. Say you had 42 nodes and some of those were the same, how it would apply the copy instruction with the count? Much easier for a diff to use the exact node order of two documents. One interesting reading I've found here about why node order can be important.
Thanks.
If the document structure is known, I think you can simply sort the necessary parts. Here's a useful acticle about it. Based on it, I've poked on some examples and could sort a document by node values (just for example), please look here
document library.xml
<?xml version="1.0"?>
<library>
<book id="1003">
<title>Jquery MVC</title>
<author>Me</author>
<price>500</price>
</book>
<book id="1001">
<title>Php</title>
<author>Me</author>
<price>600</price>
</book>
<book id="1002">
<title>Where to use IFrame</title>
<author>Me</author>
<price>300</price>
</book>
<book id="1002">
<title>American dream</title>
<author>Hello</author>
<price>300</price>
</book>
</library>
The PHP code, sorting by the <title>
<?php
$dom = new DOMDocument();
$dom->load('library.xml');
$xp = new DOMXPath($dom);
$booklist = $xp->query('/library/book');
$books = iterator_to_array($booklist);
function sort_by_title_node($a, $b)
{
$x = $a->getElementsByTagName('title')->item(0);
$y = $b->getElementsByTagName('title')->item(0);
return strcmp($x->nodeValue, $y->nodeValue) > 0;
}
usort($books, 'sort_by_title_node');
$newdom = new DOMDocument("1.0");
$newdom->formatOutput = true;
$root = $newdom->createElement("library");
$newdom->appendChild($root);
foreach ($books as $b) {
$node = $newdom->importNode($b,true);
$root->appendChild($newdom->importNode($b,true));
}
echo $newdom->saveXML();
And here's the result:
<?xml version="1.0"?>
<library>
<book id="1002">
<title>American dream</title>
<author>Hello</author>
<price>300</price>
</book>
<book id="1003">
<title>Jquery MVC</title>
<author>Me</author>
<price>500</price>
</book>
<book id="1001">
<title>Php</title>
<author>Me</author>
<price>600</price>
</book>
<book id="1002">
<title>Where to use IFrame</title>
<author>Me</author>
<price>300</price>
</book>
</library>
This way you can sort the parts of the document before comparing. After that you can even use the DOM comparison directly. Even you could reorder the nodes, it were a similar approach.
I'm not sure it'll be very useful in the case if you have a variable node number. Say if the <NDC> tag were repeated some random number of times and it's values were completely different.
And after all, I still think the simplest way were to ask your supplicant to create some more predictable document structure :)
Thanks
Anatol
I have this kind of XML:
<?xml version="1.0" encoding="utf-8"?>
<data>
<stats>
</stats>
<params>
</params>
<results>
<record id='SJDGH'>
<item>abc</item>
<item>def</item>
<item>ghi</item>
</record>
<record id='OIIO'>
<item>abc</item>
<item>def</item>
<item>ghi</item>
</record>
</results>
</data>
I'm generating a new <item> for every <record> in <results> in a loop:
// $data is SimpleXml objec from XML above
foreach ($data->results->record as $record)
{
$newitem = 'New item!'.time().$record->attributes()->id;
}
Somehow in this loop i need to change the SimpleXML object ($data) to contain new items in every <record>.
is it possible?
I needed a little guessing, but this might what you're looking for:
$records = $data->results->record;
foreach($records as $record)
{
$value = sprintf('New Item! %s / id:%s', time(), $record['id']);
$record->item[] = $value;
}
$data->asXML('php://output');
See it in action.
I think you might want to use addChild.
Check it out here: http://php.net/manual/en/simplexmlelement.addchild.php
I am very new to Zend Framework. And i have tried to get the XML value but cant make it work.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<result count="2">
<blocks>
<listing>
<title>Title 1</title>
<id>1</id>
</listing>
<listing>
<title>Title 2</title>
<id>2</id>
</listing>
</blocks>
</result>
PHP (to find all the title):
$dom = new Zend_Dom_Query();
$dom->setDocumentXml($result);
$results = $dom->queryXpath('/result/blocks/listing/title');
//$dom->queryXpath('/*/*/listing'); no luck
//$dom->queryXpath('///listing'); no luck
foreach($results as $k)
{
Zend_Debug::dump($k->getAttribute('title')); // empty
echo $k->getDocument(); // shows none
}
Any help?
Using queryXpath('/result/blocks/listing/title') your $k already is the DOMElement that represents the <tile>...</title> elements.
You can retrieve the value via $k->nodeValue. For a DOMElement that's the concatenation of all text nodes in the descendant axis.
foreach($results as $k)
{
Zend_Debug::dump($k->nodeValue); // empty
}
title is a node - not an attribute - attributes are placed inside the tag :)