首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

XSLTProcessor registerPHPFunctions 命名空間缺失導致 PHP 函數無法調用

     編輯:PHP 相關知識

問題現象

在 XSLT 中調用 PHP 函數時出現錯誤:

Warning: XSLTProcessor::transformToXml(): xmlXPathCompOpEval: function function bound to undefined prefix php
Warning: XSLTProcessor::transformToXml(): xmlXPathCompiledEval: 1 objects left on the stack

根本原因

XSLT 樣式表中未聲明 PHP 命名空間,導致 XPath 解析器無法識別 `php:function()` 前綴。

解決方案:添加 PHP 命名空間聲明

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
    xmlns:php="https://php.net/xsl">  <!-- 關鍵:聲明 PHP 命名空間 -->
    
    <xsl:output method="html" encoding="utf-8" indent="yes"/>
    
    <xsl:template match="allusers">
        <html><body>
            <h2>Users</h2>
            <table>
                <xsl:for-each select="user">
                    <tr><td>
                        <!-- 調用 PHP ucfirst 函數 -->
                        <xsl:value-of select="php:function('ucfirst', string(uid))"/>
                    </td></tr>
                </xsl:for-each>
            </table>
        </body></html>
    </xsl:template>
</xsl:stylesheet>

完整 PHP 代碼示例

<?php
$xml = <<<XML
<allusers>
    <user><uid>bob</uid></user>
    <user><uid>joe</uid></user>
</allusers>
XML;

$xsl = <<<XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="https://www.w3.org/1999/XSL/Transform"
    xmlns:php="https://php.net/xsl">
    <xsl:output method="html" encoding="utf-8" indent="yes"/>
    <xsl:template match="allusers">
        <html><body>
            <h2>Users</h2>
            <table>
                <xsl:for-each select="user">
                    <tr><td><xsl:value-of select="php:function('ucfirst', string(uid))"/></td></tr>
                </xsl:for-each>
            </table>
        </body></html>
    </xsl:template>
</xsl:stylesheet>
XSL;

$xmldoc = new DOMDocument();
$xmldoc->loadXML($xml);

$xsldoc = new DOMDocument();
$xsldoc->loadXML($xsl);

$proc = new XSLTProcessor();
$proc->registerPHPFunctions(); // 註冊 PHP 函數支持
$proc->importStyleSheet($xsldoc);

echo $proc->transformToXML($xmldoc);
// 輸出:Bob, Joe (首字母大寫)
?>

進階用法

調用靜態方法/類方法

<xsl:value-of select="php:function('MyClass::staticMethod', 'arg')"/>
<xsl:value-of select="php:function(array('MyClass', 'staticMethod'), 'arg')"/>

調用實例方法 (需先註冊實例)

<?php
$obj = new MyClass();
$proc->registerPHPFunctions(); // 全局函數
// 實例方法需通過閉包或靜態包裝調用
$proc->registerPHPFunctions(['myFunc' => [$obj, 'method']]); // 不直接支持
?>

傳遞節點集合

<xsl:value-of select="php:function('processNodes', .)"/>
<?php
function processNodes($nodes) {
    // $nodes 是 DOMNodeList
    foreach ($nodes as $node) { ... }
    return $result;
}
?>

常見錯誤排查

錯誤信息原因解決
undefined prefix php缺少 xmlns:php 聲明添加 xmlns:php="https://php.net/xsl"
function bound to undefined prefix同左同左
objects left on stackXPath 表達式結果未正確消費檢查 select 表達式、確保單一結果
PHP function 'xxx' not found函數名拼寫錯誤或未定義檢查函數名、命名空間、可見性
DOMDocument::loadXML() errorXML/XSL 格式錯誤驗證 XML 格式、編碼聲明

安全考量

  • 僅暴露必要函數:`$proc->registerPHPFunctions(['allowed_func1', 'allowed_func2'])`
  • 禁用危險函數:`exec`, `shell_exec`, `system`, `eval`, `file_get_contents` 等
  • 輸入驗證:XSLT 參數來自用戶輸入時必須過濾
  • 禁用外部實體:`libxml_disable_entity_loader(true)` 防 XXE

版本要求

  • PHP 5.1+ 支持 `registerPHPFunctions()`
  • libxslt 1.1.0+ (通常系統自帶滿足)
  • PHP 編譯需 `--with-xsl` (默認包含)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved