Wednesday, 7 April 2010

<?xml version="1.0"?> Removal using PHP

I've been working on something for ages which involved creating some XML formatted data using PHP. PHPs implementation of XML has come on leaps and bounds, it seems, and I must admit to being pretty happy with the results using PHPs DOM implementation. So I uploaded the XML to its target API and nothing happened. And nothing kept happening, over and over again...

After a fair bit of head-scratching and trying any number of things. I tried to see if the XML was broken somehow and managed to run foul of trying to print an XML Object before converting it to a string with saveXML()... oops! Then I thought about the XML Prolog and how the examples of using the API I'd seen hadn't had the whole <?xml version="1.0"?> at the beginning of the XML. Now how was a going to get rid of it?

At first I just echoed the XML to a browser and copied the resultant XML into Boxer (and sure, who wouldn't use Boxer with it's lovely Format XML tool?). Then I removed the Prolog and copied it into a string variable using the "here document" syntax and tried to upload that and all worked well. A bit clunky but it worked!.

How to remove the Prolog programmatically though?

I got to thinking about my initial fascination with XML and the stuff I read in 2004 or so and remembered XSL. PHP can use XSL so I did a bit of research and came up with this XSL file:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes"/>
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Then it was a simple matter to put the following in the script:

  // Load XML file
  $xsl = new DOMDocument;
  $xsl->load('removeProlog.xsl', LIBXML_NOCDATA);

  // Configure the transformer
  $proc = new XSLTProcessor;
  // and attach the xsl rules
  $proc->importStyleSheet($xsl); 

  // Replace the XML with the transformed XML
  $xml = $proc->transformToXML($xml);

Hey Presto, all done and my hair can get back to growing ;-)

4 comments:

  1. Hi,
    I got an error, can you have a look?


    ...
    $xml = $proc->transformToXML($xml);
    print $xml ->saveXML();

    Fatal error: Call to a member function saveXML() on a non-object.

    I doubled checked to be sure about the $xml file, the print line works if I put it before transformToXML line.

    Thank you very much indeed

    ReplyDelete
  2. Hi there,
    I'm guessing that there might be a number of issues. Have you referenced the removeProlog.xsl file correctly? It need to be visible to the XSLTProcessor class:

    // Load XML file
    $xsl = new DOMDocument;
    $xsl->load('removeProlog.xsl', LIBXML_NOCDATA);

    Cheers,

    Dom

    ReplyDelete
  3. I constructed the xsl file by copying the below to the notepad++ and saved as xml, then changed the extension to xsl. May be this is
    the reason?

    ReplyDelete
  4. Hi,

    that shouldn't have made a difference but just to check please use the file here: http://drmsite.com/removeProlog.xsl.

    Let me know how you get on.

    Cheers,

    Dom

    ReplyDelete