如何在带有registerPHPFunctions的XSLT中使用DOMDocumentFragment?

时间:2013-12-03 19:52:47

标签: php dom xslt

请参阅“it works”“it not works”是我的代码的错误还是DOMDocument-PHP实现的错误?


如果您不熟悉XSLT和 registerPHPFunctions ,请参阅this link for context and preparations。假设按字符串输入,

 function XSL_transf($xml,$xsl) {
         $xmldoc = DOMDocument::loadXML($xml);
         $xsldoc = DOMDocument::loadXML($xsl);
         $proc = new XSLTProcessor();
         $proc->registerPHPFunctions();  // here
         $proc->importStyleSheet($xsldoc);
         echo $proc->transformToXML($xmldoc);
 }
 $xml='<root/>'; //simplest
 $xsl = <<<'EOB'
 <?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:php="http://php.net/xsl">
       ... HERE COPY/PASTE YOUR XSLT template ...
 </xsl:stylesheet>
 EOB;

它有效

条款<xsl:copy-of ... />收到 DOMElement DOMDocument 和(为什么不呢?) DOMDocumentFragment 。 所以,如果我们有一个返回DOMDocument的PHP函数,我们可以使用它。

function foo1() {
    $dom = DOMDocument::loadXML('<t> foo <tt val="123"/> bar </t>');
    return $dom; 
}

foo1调用到模板中

<xsl:template match="/">
   PHP foo1()=<xsl:copy-of select="php:function('foo1')" />
</xsl:template>

结果(您可以使用XSL_transf($xml,$xsl)查看):

 <t> foo <tt val="123"/> bar </t>

它不起作用

通过

更改上面的功能
function foo1() {
    $dom = new DOMDocument;
    $tmp = $dom->createDocumentFragment();
    $tmp->appendXML('<t> foo <tt val="123"/> bar </t> test'); 
    return $tmp;
}

RESULT为空。没有错误消息,但没有结果。

2 个答案:

答案 0 :(得分:3)

您可以使用以下XPath表达式解决:

php:function('foo1')/node()

现在,这是一个PHP错误吗?还是一个libxml2错误?很难说,因为如果查看specifications of XPath 1.0,就找不到任何文档片段的引用。最相似的是 root node ,它也是用于表示文档的节点。

我认为问题来自PHP,when it constructs the node set to be returned。它不应该返回整个文档片段节点,而是返回由其内容形成的 nodeset

然而,我可能完全错了,因为我从未使用过libxml2而且我不知道它是如何工作的。

答案 1 :(得分:0)

我不知道是否有关于可以通过registerPHPFunctions()调用的函数返回什么数据的文档。有疑问,你必须检查libxml2 / libxslt(http://xmlsoft.org/)的来源。

也许你的第二个例子不起作用的原因是它在单个根元素方面不包含有效的xml。最后的“测试”一词是与元素&lt; t&gt;相同级别的文本节点。之前。测试切割文本节点或包装根节点。 DocumentFragment包含多个元素,但似乎没有正确返回。

如果第二个示例不起作用,则可能根本不支持返回DocumentFragments。

@Peter Krauss:对于空节点集,不发送错误消息是xml的常见行为。我自己使用libxslt函数,但只发送了纯文本。当我尝试发送数组时,我失败了。也许对你而言,这是一种只使用文本并将其转换为xslt端的节点集的方法吗?