SimpleXML and namespaces

    Kevin Yank
    Kevin Yank
    Share

    There’s a lot about SimpleXML, PHP5’s new API for accessing the contents of XML documents, in SitePoint’s recently-published book No Nonsense XML Web Development With PHP, but one thing it doesn’t cover is how to use SimpleXML with a document that makes use of XML Namespaces. Take this document, for example–a simplified RSS 1.0 feed:

    
    <?xml version="1.0" encoding="utf-8"?>
    <rdf:RDF xmlns:rdf="https://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/">
      <channel rdf:about="https://www.sitepoint.com/">
        <title>SitePoint.com</title>
        <link>https://www.sitepoint.com/</link>
        <description>SitePoint is the natural place to go to grow your online business.</description>
        <items>
          <rdf:Seq>
            <rdf:li rdf:resource="https://www.sitepoint.com/article/take-command-ajax" />
          </rdf:Seq>
        </items>
      </channel>
      <item rdf:about="https://www.sitepoint.com/article/take-command-ajax">
        <title>Take Command with AJAX</title>
        <link>https://www.sitepoint.com/article/take-command-ajax</link>
        <description>Want to get a bang out of your AJAX artillery?</description>
        <dc:date>2005-10-14T04:00:00Z</dc:date>
      </item>
    </rdf:RDF>
    
    In PHP5, here’s how you might think to use SimpleXML’s API to get at the date of every item in the feed:
    
    $feed = simplexml_load_file('https://www.sitepoint.com/recent.rdf');
    foreach ($feed->item as $item) {
      echo $item->date;
    }
    
    But this won’t work, because the date
    element has a namespace prefix (<dc:date>), so it can’t be accessed by the usual means. Here’s the solution. First, check what the URI is for the namespace. In this case, the dc: prefix maps to the URI http://purl.org/dc/elements/1.1/:
    <rdf:RDF xmlns:rdf="https://www.w3.org/1999/02/22-rdf-syntax-ns#"
        xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/">
    Then use the children method
    of the SimpleXML object, passing it that URI:
    
    $feed = simplexml_load_file('https://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;
    }
    
    When you pass the namespace URI to the children method, you get a SimpleXML collection of the child elements belonging to that namespace. You can work with that collection the same way you would with any SimpleXML collection. You can use the attributes method in the same way to obtain attributes with namespace prefixes.

    Frequently Asked Questions (FAQs) about SimpleXML and Namespaces

    What is the purpose of namespaces in SimpleXML?

    Namespaces in SimpleXML are used to differentiate between elements that have the same name but belong to different vocabularies. They provide a way to avoid conflicts between element names. A namespace is a collection of names identified by a URI reference. Elements and attributes from different namespaces can co-exist in a single XML document without any conflicts.

    How do I use namespaces in SimpleXML?

    To use namespaces in SimpleXML, you need to register the namespace using the registerXPathNamespace method. This method takes two parameters: the prefix and the URI of the namespace. Once the namespace is registered, you can use the prefix to access elements in that namespace.

    How do I parse XML with namespaces using SimpleXML?

    Parsing XML with namespaces in SimpleXML involves a few steps. First, you need to load the XML document using the simplexml_load_string or simplexml_load_file function. Then, you need to register the namespace using the registerXPathNamespace method. Finally, you can use the xpath method to query elements in the namespace.

    How do I fetch namespaced XML elements with SimpleXML?

    To fetch namespaced XML elements with SimpleXML, you need to use the children method with the namespace URI as the parameter. This will return all the child elements in that namespace. You can then iterate over these elements using a foreach loop.

    What is the difference between getNamespaces and registerXPathNamespace methods in SimpleXML?

    The getNamespaces method in SimpleXML returns an array of namespaces used in the XML document. On the other hand, the registerXPathNamespace method is used to register a namespace for use in XPath queries. It does not return any value.

    Can I use multiple namespaces in a single XML document with SimpleXML?

    Yes, you can use multiple namespaces in a single XML document with SimpleXML. Each namespace should have a unique prefix and URI. You can register each namespace using the registerXPathNamespace method and then use the prefix to access elements in that namespace.

    How do I handle default namespaces in SimpleXML?

    To handle default namespaces in SimpleXML, you can use the children method with the namespace URI as the parameter. This will return all the child elements in the default namespace. You can then iterate over these elements using a foreach loop.

    Can I modify namespaced XML elements with SimpleXML?

    Yes, you can modify namespaced XML elements with SimpleXML. You can use the addChild method to add a new child element in a namespace. To modify an existing element, you can simply assign a new value to it.

    How do I handle namespace prefixes in SimpleXML?

    Namespace prefixes in SimpleXML are handled using the registerXPathNamespace method. This method takes two parameters: the prefix and the URI of the namespace. Once the namespace is registered, you can use the prefix to access elements in that namespace.

    Can I use XPath with namespaces in SimpleXML?

    Yes, you can use XPath with namespaces in SimpleXML. After registering the namespace using the registerXPathNamespace method, you can use the xpath method to query elements in the namespace. The XPath expression should use the registered prefix to refer to elements in the namespace.