Viewed   86 times

I'm trying to read an RSS feed from Flickr but it has some nodes which are not readable by Simple XML (media:thumbnail, flickr:profile, and so on).

How do I get round this? My head hurts when I look at the documentation for the DOM. So I'd like to avoid it as I don't want to learn.

I'm trying to get the thumbnail by the way.

 Answers

3

The solution is explained in this nice article. You need the children() method for accessing XML elements which contain a namespace. This code snippet is quoted from the article:

$feed = simplexml_load_file('http://www.sitepoint.com/recent.rdf'); 
foreach ($feed->item as $item) { 
    $ns_dc = $item->children('http://purl.org/dc/elements/1.1/'); 
    echo $ns_dc->date; 
}
Sunday, December 25, 2022
3

So basically what you need to do is a function that takes each <asset/> child of current node, builds the HTML then checks if the current node has <asset/> children of its own and keeps recursing deeper down the tree.

Here's how you can do it:

function printAssetMap()
{
    return printAssets(simplexml_load_file(X_ASSETS));
}

function printAssets(SimpleXMLElement $parent)
{
    $html = "<ul>n";
    foreach ($parent->asset as $asset)
    {
        $html .= printAsset($asset);
    }
    $html .= "</ul>n";

    return $html;
}

function printAsset(SimpleXMLElement $asset)
{
    $html = '<li id="asset'.$asset->asset_assetid.'"><ins>&nbsp;</ins><a href="#">'.$asset->asset_name.' ['.$asset->asset_assetid.']</a>';

    if (isset($asset->asset))
    {
        // has <asset/> children
        $html .= printAssets($asset);
    }

    $html .= "</li>n";

    return $html;
}

By the way, I would expect a function named "printX" to actually print or echo something, rather than return it. Perhaps you should name those functions "buildX" ?

Saturday, September 17, 2022
 
shdr
 
1

Here is some example code that I hope can point you in the right direction. Essentially, it is walking the DOMDocument echoing the element name and values. Note that the whitespace between the elements is significant, so for the purposes of the demo, the XML is compacted. You may find a similar issue loading from a file, so if you are not getting the expected output you might need to strip whitespace nodes.

You could replace the //root/* with a different XPath for example //people if you only wanted the <people> elements.

<?php
    $xml = <<<XML
    <root><start_info><info tabindex="1"><infonumber>1</infonumber><trees>green</trees></info></start_info>
    <people><pe><people_ages><range number="1"><age value="1">1</age><age value="2">2</age></range></people_ages></pe></people>
    </root>
    XML;

    $dom = new DOMDocument();
    $dom->recover = true;
    $dom->loadXML($xml);
    $xpath = new DOMXPath($dom);
    $nodelist = $xpath->query('//root/*');
    foreach ($nodelist as $node) {
        echo "n$node->tagName";
        getData($node);
    }

    function getData($node) {
        foreach ($node->childNodes as $child) {

            if ($child->nodeType == XML_ELEMENT_NODE) {
                echo ($child->tagName === '' ? '' : "n").$child->tagName;
            }

            if ($child->nodeType == XML_TEXT_NODE) {
                echo '->'.$child->nodeValue;
            }

            if ($child->hasChildNodes()) {
                getData($child); // recursive call
            }
        }
    }
?>
Sunday, October 16, 2022
4

Using recursion, you can create a brand new document based on the input, solving all your points at once:

Code

<?php

$input = file_get_contents('http://www.fluffyduck.com.au/sampleXML.xml');
$inputDoc = new DOMDocument();
$inputDoc->loadXML($input);

$outputDoc = new DOMDocument("1.0", "utf-8");
$outputDoc->appendChild($outputDoc->createElement("root"));

function ConvertUserToItem($outputDoc, $inputNode, $outputNode)
{
    if ($inputNode->hasChildNodes())
    {
        foreach ($inputNode->childNodes as $inputChild)
        {
            if (strtolower($inputChild->nodeName) == "user")
            {
                $outputChild = $outputDoc->createElement("item");
                $outputNode->appendChild($outputChild);
                // read input attributes and convert them to nodes
                if ($inputChild->hasAttributes())
                {
                    $outputContent = $outputDoc->createElement("content");
                    foreach ($inputChild->attributes as $attribute)
                    {
                        if (strtolower($attribute->name) != "id")
                        {
                            $outputContent->appendChild($outputDoc->createElement($attribute->name, $attribute->value));
                        }
                        else
                        {
                            $outputChild->setAttribute($attribute->name, $attribute->value);
                        }
                    }               
                    $outputChild->appendChild($outputContent);
                }
                // recursive call
                ConvertUserToItem($outputDoc, $inputChild, $outputChild);
            }
        }
    }
}

ConvertUserToItem($outputDoc, $inputDoc->documentElement, $outputDoc->documentElement);

header("Content-Type: text/xml; charset=" . $outputDoc->encoding);
echo $outputDoc->saveXML();
?>

Output

<?xml version="1.0" encoding="utf-8"?>
<root>
    <item id="41">
        <content>
            <username>bsmain</username>
            <firstname>Boss</firstname>
            <lastname>MyTest</lastname>
            <fullname>Test Name</fullname>
            <email>lalal@test.com</email>
            <logins>1964</logins>
            <lastseen>11/09/2012</lastseen>
        </content>
        <item id="61">
            <content>
                <username>underling</username>
                <firstname>Under</firstname>
                <lastname>MyTest</lastname>
                <fullname>Test Name</fullname>
                <email>lalal@test.com</email>
                <logins>4</logins>
                <lastseen>08/09/2009</lastseen>
            </content>
        </item>
...
Friday, December 9, 2022
 
petele
 
2

Your example fragment is not quite correct, since it does not include an XML namespace binding for the xlink: prefix. What you probably want is:

<g xmlns:xlink="http://www.w3.org/1999/xlink">
  <a xlink:href="http://example.com" data-bind="121">lala</a>
</g>

You can unmarshal this attribute using the namespace URL:

XlinkHref string `xml:"http://www.w3.org/1999/xlink href,attr"`

Here is an updated copy of your example program with the namespace fix.

Monday, August 1, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :