1

I want to integrate an XSL file in an XML string gived me by php CURL command. I tryed this

$output = XML gived me by curl option;
$hotel = simplexml_load_string($output);
$hotel->addAttribute('?xml-stylesheet type=”text/xsl” href=”css/stile.xsl”?');
echo $hotel->asXML();

Doing this when I see the XML on browser, I receive the file without the stylesheet. Where is my error?

hakre
  • 193,403
  • 52
  • 435
  • 836
  • What are `”`? Does it work the same way as `"`?... And what is your error? – brbcoding May 15 '13 at 13:59
  • Sorry now I have edited: Doing this when I see the XML on browser, I receive the file without the stylesheet. Where is my error? – antonio esposito May 15 '13 at 14:07
  • That's kind of what I'm saying... What try replacing those `”` with `"` – brbcoding May 15 '13 at 14:07
  • I have tried now, but is the same – antonio esposito May 15 '13 at 14:11
  • I would not not how to do this with SimpleXML... I'd use [`DOM::CreateProcessingInstruction`](http://www.php.net/manual/en/domdocument.createprocessinginstruction.php) (a processing instruction is NOT a regular element), you can always convert if to/from `SimpleXML` whenever you like. – Wrikken May 15 '13 at 14:18
  • I tried this now with exemple of php manual: $xslt = $output->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="css/stile.xsl"'); $output->appendChild($xslt); echo $output->asXML(); but the page is blank with this – antonio esposito May 15 '13 at 14:44
  • @antonio esposito: You need to import into DOM first, I added an example as an answer that shows how this can be done (it's not the only way, just one example). Also if you get a blank page, you have missed to enable error reporting to the highest level in development and tracking the error log / display: [How to get useful error messages in PHP?](http://stackoverflow.com/a/14504459/367456) – hakre May 15 '13 at 15:01

1 Answers1

3

A SimpleXMLElement does not allow you by default to create and add a Processing Instruction (PI) to a node. However the sister library DOMDocument allows this. You can marry the two by extending from SimpleXMLElement and create a function to provide that feature:

class MySimpleXMLElement extends SimpleXMLElement
{
    public function addProcessingInstruction($target, $data = NULL) {
        $node   = dom_import_simplexml($this);
        $pi     = $node->ownerDocument->createProcessingInstruction($target, $data);
        $result = $node->appendChild($pi);
        return $this;
    }
}

This then is easy to use:

$output = '<hotel/>';
$hotel  = simplexml_load_string($output, 'MySimpleXMLElement');
$hotel->addProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="style.xsl"');
$hotel->asXML('php://output');

Exemplary output (beautified):

<?xml version="1.0"?>
<hotel>
  <?xml-stylesheet type="text/xsl" href="style.xsl"?>
</hotel>

Another way is to insert an XML chunk to a simplexml element: "PHP SimpleXML: insert node at certain position" or "Insert XML into a SimpleXMLElement".

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • beautiful, but it insert the stylesheet at the end of the XML string, can it generate any problems? – antonio esposito May 15 '13 at 15:03
  • Try, I dunno ;) The alternative is to not append but to [insert before](http://php.net/domnode.insertbefore) if the node [contains children](http://php.net/domnode#domnode.props.childnodes). - Just seeing you actually do not even need to test. Instead of `->appendChild(...);` it is: `->insertBefore($pi, $node->childNodes->item(0));` - Demo: http://eval.in/30382 – hakre May 15 '13 at 15:08
  • perfect, but it don't recognize the xls, if I see with firebug on firefox there is: such as commented. – antonio esposito May 15 '13 at 15:58
  • Well in my example it works, you must have made some error then I suppose. Add your code-example as an example here: http://eval.in – hakre May 15 '13 at 15:59
  • Please check, it's not complete: *"Fatal error: Call to undefined function curl_exec() in /tmp/execpad-9de4c07387f6/source-9de4c07387f6 on line 3"* in http://eval.in/private/6931bf95a20486 – hakre May 15 '13 at 16:12
  • if I insert all the php the error is "Fatal error: Call to undefined function curl_init() in /tmp/execpad-0a00a6a3187b/source-0a00a6a3187b on line 21" I receive the xml with curl: http://eval.in/30396 – antonio esposito May 15 '13 at 16:16
  • Yes, because eval.in does not support curl there. However I can run it on my end. My first tip for you is: http://stackoverflow.com/a/5225131/367456 – hakre May 15 '13 at 16:31
  • Second tip: Use SimpleXMLElement to build your XML request post-data. http://php.net/simplexml.examples-basic – hakre May 15 '13 at 16:38
  • As written, I do not get a problem, here is the variant I currently use: https://gist.github.com/hakre/5585567 - It also shows you how you can use an array for parameters and how to use SimpleXML as well to create the XML more easily like you need it for the request :-) – hakre May 15 '13 at 17:10
  • But using this I have this errors: Warning: simplexml_load_string() expects parameter 2 to be a class name derived from SimpleXMLElement, 'MySimpleXMLElement' given in /tmp/execpad-b690598e4523/source-b690598e4523 on line 53 Fatal error: Call to a member function addProcessingInstruction() on a non-object in /tmp/execpad-b690598e4523/source-b690598e4523 on line 54 – antonio esposito May 15 '13 at 17:59
  • You need to define that class `MySimpleXMLElement`, it is in the answer here (not part of the gist). I mean this is where we have this class, rigth? :) – hakre May 15 '13 at 18:17
  • I' ve done all of this, but is the same initial problem: on firefox there is: such as commented – antonio esposito May 16 '13 at 07:40
  • But for the request to the server that you have done on github, if I want to do a GET request I have to change only the method? – antonio esposito May 16 '13 at 11:14
  • A bit more. You change the method and you have to move the paraemters into the URL (out of the `"content"` setting). – hakre May 16 '13 at 12:33
  • @antonioesposito: `content` as array key in `$context = stream_context_create(array('http' => array(` - and you can add the params to the URL with the array params as well so the difference between the POST and GET code is not that much. – hakre May 17 '13 at 10:55