dongpuchao1680 2014-06-05 22:20
浏览 23
已采纳

带样式表的CakePHP XmlView(XSL)

I'm using cakephp's Xml or XmlView with _serialize to translate an array to xml, however I cannot add a stylesheet declaration.

Is it possible to add: into the XML before the root tag when using Array to XML?

Sample code:

$value = array(
    'tags' => array(
        'tag' => array(
            array(
                'id' => '1',
                'name' => 'defect'
            ),
            array(
                'id' => '2',
                'name' => 'enhancement'
        )
        )
    )
);
$xml = Xml::build($value);
echo $xml->asXML();
  • 写回答

1条回答 默认 最新

  • douxiong4892 2014-06-05 23:28
    关注

    Use built-in DOMDocument methods

    Xml::build() returns an instance of either SimpleXMLElement (default) or DOMDocument. The latter has a built-in method for creating processing instruction nodes, DOMDocument::createProcessingInstruction().

    $xml = Xml::build($value, array('return' => 'domdocument'));
    $style = $xml->createProcessingInstruction(
        'xml-stylesheet',
        'type="text/xsl" href="/path/to/style.xsl"'
    );
    $xml->insertBefore($style, $xml->firstChild);
    echo $xml->saveXML();
    

    This would output something like:

    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet type="text/xsl" href="/path/to/style.xsl"?>
    <tags>
        ...
    </tags>
    

    See also

    Manipulating XmlView output

    When using XmlView there is no way to hook into the XML generation process, as it's finally generated using a simple one-liner:

    return Xml::fromArray($data, $options)->asXML();
    

    So the only option here would be to take the generated output and process it again. For example extend the XmlView, override the _serialize() method, and then take that generated output, create a new DOMDocument instance from it, and add the PI nodes if necessary.

    Here's an (untested) example of such an exteneded view:

    App::uses('XmlView', 'View');
    
    class MyXmlView extends XmlView {
        protected function _serialize($serialize) {
            $xml = parent::_serialize($serialize);
    
            if(isset($this->viewVars['_processingInstructions'])) {
                $pi = array_reverse($this->viewVars['_processingInstructions']);
    
                $doc = new DOMDocument();
                $doc->loadXML($xml);
    
                foreach($pi as $instruction) {
                    $node = $doc->createProcessingInstruction(
                        current(array_keys($instruction)),
                        current($instruction)
                    );
                    $doc->insertBefore($node, $doc->firstChild);
                }
    
                $xml = $doc->saveXML();
            }
    
            return $xml;
        }
    }
    

    In the controller one could then set the _processingInstructions view variable to define PI nodes:

    $_processingInstructions = array(
        array('xml-stylesheet' => 'type="text/xsl" href="/path/to/style.xsl"')
    );
    
    $this->set(compact('tags', '_processingInstructions'));
    $this->set('_serialize', 'tags');
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 关于#python#的问题:自动化测试