carica / xpath-functions
为PHP的ext/xslt提供类似XPath 2/3的功能
dev-master
2022-11-23 18:02 UTC
Requires
- php: >= 8.0
- ext-dom: *
- ext-intl: *
- ext-json: *
- ext-xsl: *
This package is auto-updated.
Last update: 2024-09-23 21:53:31 UTC
README
本项目尝试为PHP的XSLTProcessor添加Xpath 2/3函数。由于某些语法不可用,完整的实现是不可能的。但让我们看看能做多少。
如果您有一个希望添加的功能,请提出一个issue。
工作原理
- 通过
Carica\XpathFunctions\XSLTProcessor
扩展XSLTProcessor
- 为XSLTProcessor实现一个回调,用于调用特定的PHP函数
- 添加一个流包装器来加载XSLT模板,这些模板将回调包装成XPath函数,使用EXSLT或直接实现该函数。
安装
composer require carica/xpath-functions
用法
- 为函数定义命名空间
- 将模块导入您的XSLT
- 调用XPath函数
第2步是XSLT 2/3的区别。您需要导入包含您想使用的函数的模块模板。
妥协
Xpath/XSLT 1.0没有其后继者的广泛类型系统。因此,大多数函数返回更基本的数据类型。数组和使用XDM节点模拟,序列作为XDM数组。
示例
使用字符串比较
// import extended XSLTProcessor use Carica\XpathFunctions\XSLTProcessor; $xslt = <<<'XSLT' <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fn"> <!-- ^- define the function namespace --> <!-- import the string comparsion module --> <xsl:import href="xpath-functions://Strings/Comparsion"/> <xsl:output indent="yes" method="xml"/> <xsl:template match="/names"> <html lang="en"> <body> <div> <header>Exactly</header> <xsl:for-each select="name[fn:compare(., 'André') = 0]"> <span><xsl:value-of select="."/></span> </xsl:for-each> </div> <div> <header>Case Insensitive, Ignore Accents</header> <xsl:variable name="collation">http://www.w3.org/2013/collation/UCA?strength=primary</xsl:variable> <xsl:for-each select="name[fn:compare(., 'andre', $collation) = 0]"> <span><xsl:value-of select="."/></span> </xsl:for-each> </div> </body> </html> </xsl:template> </xsl:stylesheet> XSLT; $xml = <<<'XML' <?xml version="1.0"?> <names> <name>Andreas</name> <name>Andre</name> <name>André</name> <name>Andrè</name> </names> XML; $stylesheet = new DOMDocument(); $stylesheet->loadXML($xslt); $input = new DOMDocument(); $input->loadXML($xml); $processor = new XSLTProcessor(); $processor->importStylesheet($stylesheet); echo $processor->transformToXml($input);
输出
<?xml version="1.0"?> <html lang="en"> <body> <div> <header>Exactly</header> <span>André</span> </div> <div> <header>Case Insensitive, Ignore Accents</header> <span>Andre</span> <span>André</span> <span>Andrè</span> </div> </body> </html>
使用正则表达式包装文本节点的一部分
// import extended XSLTProcessor use Carica\XpathFunctions\XSLTProcessor; $xslt = <<<'XSLT' <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fn"> <!-- import RegExp functions --> <xsl:import href="xpath-functions://Strings/RegExp"/> <xsl:template match="speak//text()"> <!-- use RegExp function --> <xsl:for-each select="fn:analyze-string(., '\d+')/*"> <xsl:choose> <xsl:when test="local-name() = 'match'"> <say-as interpret-as="characters"><xsl:value-of select="."/></say-as> </xsl:when> <xsl:otherwise> <xsl:value-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> <xsl:template match="*"> <xsl:element name="{name()}"> <xsl:copy-of select="@*"/> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet> XSLT; $xml = <<<'XML' <?xml version="1.0"?> <speak>The test number is 123456789, and some further block of text.</speak> XML; $stylesheet = new DOMDocument(); $stylesheet->loadXML($xslt); $input = new DOMDocument(); $input->loadXML($xml); $processor = new XSLTProcessor(); $processor->importStylesheet($stylesheet); echo $processor->transformToXml($input);
输出
<?xml version="1.0"?> <speak>The test number is <say-as interpret-as="characters">123456789</say-as>, and some further block of text.</speak>