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 关于#java#的问题:找一份能快速看完mooc视频的代码
  • ¥15 这种微信登录授权 谁可以做啊
  • ¥15 请问我该如何添加自己的数据去运行蚁群算法代码
  • ¥20 用HslCommunication 连接欧姆龙 plc有时会连接失败。报异常为“未知错误”
  • ¥15 网络设备配置与管理这个该怎么弄
  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!