bluem / xmltransformer
用于将 XML 转换为 XML、HTML、纯文本等的 PHP 库
Requires
- php: >=7.0
Requires (Dev)
- phpunit/phpunit: ^6.0
README
概述
XMLTransformer 是一个 PHP 库,可以将任何类型的输入 XML 转换为输出字符串。这个输出字符串不一定是 XML,也可以是 HTML 或纯文本。
转换
XMLTransformer 能够 ...
- 删除标签,包括或不包括标签内容
- 重命名属性
- 删除属性
- 添加属性
- 更改属性值
- 在标签前后插入内容
- 在标签内容开始或结束时插入内容
- 通过传递到用户定义的闭包来转换包括所有内容的标签
- 执行上述组合中的任何操作
- 修改文本节点的内容
何时使用
在我看来,如果输入 XML 和要生成的输出结构相似,XMLTransformer 的性能非常好。此外,如果输入 XML 的数据需要由现有的 PHP 代码库进行处理,使用 XMLTransformer 而不是 XSL-T 可能更干净、更简单。
何时不使用
当需要重新排列输入数据时,你可能更倾向于使用 XSL-T,因为这是 XMLTransformer 不提供的功能。(尽管在一定程度上可以通过适当的回调代码完成。)当然,如果你觉得一个不够用,你可以自由地将 XSL-T 与 XMLTransformer 结合使用,以取长补短。
安装
推荐通过 Composer 安装此库。为此,请将 "bluem/xmltransformer": "~2.0"
添加到你的 composer.json
文件中的需求中。由于该库使用 语义版本控制,你将获得修复和功能添加,但不会得到破坏 API 的更改。
或者,你可以使用 git 克隆存储库或下载一个 存档发布版。
使用方法
你将输入 XML 和回调函数或回调方法的名称(按照常规方式指定,使用 [$object, 'methodName']
语法)或匿名函数/闭包传递给 XMLTransformer
。
对于每个标签(开标签、闭标签或空标签),回调函数将使用标签的名称、其属性以及它是否是开标签、空标签或闭标签的信息来调用。现在,你的函数/方法/闭包可以返回以下三种事物之一
- 一个数组(它描述了应执行哪些转换 – 请见下文)
false
(表示:丢弃此标签、其属性以及任何标签和任何子元素)null
(表示:不修改任何内容 – 这是默认行为,即:如果回调返回空值,则不进行任何更改。)
回调函数参数
回调函数/方法/闭包使用三个参数调用
- 元素/标签名称
- 元素/标签的属性(一个关联数组,包含 name=>value 对,其中 name 包含命名空间,如果属性不是默认命名空间中的属性)
- 元素类型常量,它将是
XMLTransformer::ELEMENT_OPEN
对于开标签,XMLTransformer::ELEMENT_EMPTY
对于空标签,以及XMLTransformer::ELEMENT_CLOSE
对于闭标签。
请注意,即使对于闭合标签,属性也将始终被给出。
转换描述数组
当你想要执行转换时,你必须返回一个关联数组。在这种情况下,可以使用以下键
XMLTransformer::RULE_TAG
:对于“tag”键返回false会移除标签(包括其属性,当然),但保留任何包含的内容。返回一个字符串会将标签名称设置为该字符串。XMLTransformer::RULE_ADD_BEFORE
:将在打开标签之前插入给定的字符串XMLTransformer::RULE_ADD_AFTER
:将在闭合标签之后插入给定的字符串XMLTransformer::RULE_ADD_START
:将在打开标签之后立即插入给定的字符串XMLTransformer::RULE_ADD_END
:将在闭合标签之前立即插入给定的字符串XMLTransformer::RULE_TRANSFORM_OUTER
:值必须是一个闭包,该闭包将接收元素本身及其所有内容作为字符串。闭包的返回值将替换元素。XMLTransformer::RULE_TRANSFORM_INNER
:值必须是一个闭包,该闭包将接收元素的内容作为字符串。闭包的返回值将替换元素。
此外,为了处理属性,可以使用形式为“@”的数组键,其中是属性名称(如果有命名空间,则不是默认命名空间)。此类数组键的值可以是以下之一
- false:将移除属性
- 以“@”开头的字符串:将重命名属性
- 一个字符串:将属性值设置为该字符串。
例如,此返回数组……
return [ XMLTransformer::RULE_TAG => 'demo', '@xml:id' => 'id', '@foo' => false, XMLTransformer::RULE_ADD_AFTER => '!', ];
……表示
- 将标签重命名为“demo”
- 将“xml:id”属性重命名为“id”
- 移除“@foo”属性
- 在闭合标签之后(或直接在标签之后,如果它是空标签)插入字符串“!”
请注意,(由于XMLTransformer
不仅限于生成XML)返回数组的值不会进行自动转义。只有一个例外:属性值,因为XMLTransformer假设如果你设置了属性值,你想生成XML或HTML输出。
通过引用传递属性
回调可以接受参数数组并通过引用接收,因此允许直接操作属性。当需要更改或移除大量属性,或者预先知道属性名称的前缀、后缀(或命名空间)时,这很有用。
以下是一个示例。
示例
以下所有示例都假设你的代码包括用于Composer自动加载的常规样板代码
require 'vendor/autoload.php';
Hello world
use BlueM\XMLTransformer; echo XMLTransformer::transformString( '<root><element>Hello world</element></root>', function($tag, $attributes, $opening) { return [ XMLTransformer::RULE_TAG => false, // <-- Removes tag, but keeps content ]; } ); // Result: “Hello World”.
多语言Hello world
use BlueM\XMLTransformer; function transform($tag, $attributes, $opening) { if ('hello-world' == $tag) { if (isset($attributes['xml:lang']) and 'de' == $attributes['xml:lang']) { $str = 'Hallo Welt'; } else { $str = 'Hello world'; } return [ XMLTransformer::RULE_TAG => false, // <-- Remove the tag, keep content XMLTransformer::RULE_ADD_BEFORE => $str, // <- Insert literal content ]; } if ('root' == $tag) { // We do not want the enclosing <root> tags in the output return [XMLTransformer::RULE_TAG => false]; } } echo XMLTransformer::transformString( '<root><hello-world xml:lang="de" /></root>', 'transform' ); // Result: “Hallo Welt” echo XMLTransformer::transformString( '<root><hello-world xml:lang="en" /></root>', 'transform' ); // Result: “Hello world”
移除标签及其所有内容
echo XMLTransformer::transformString( '<root><remove>Hello </remove>World</root>', function($tag, $attributes, $opening) { switch ($tag) { case 'remove': return false; // <-- Removes tag incl. content case 'root': case 'keep': return [XMLTransformer::RULE_TAG => false]; // <-- Remove tag, keep content break; default: // Returning null is not necessary, as this // is the default behaviour. It is equivalent // to "Do not change anything." return null; } } ); // Result: “World”
更改属性值
echo XMLTransformer::transformString( '<root abc="def"></root>', function($tag, $attributes, $opening) { return [ '@abc' => 'xyz' ]; } ); // Result: “<root abc="xyz"></root>” // Please note that empty tags will always be returned with // a space before the slash.
添加、重命名和移除属性
echo XMLTransformer::transformString( '<root xml:id="abc"><bla xml:id="def" blah="yes"/></root>', function($tag, $attributes, $opening) { return [ '@foo' => 'bar', // Add attribute "foo" with value "bar" '@blah' => false, // Remove attribute "blah" '@xml:id' => '@id', // Rename attribute "xml:id" to "id" ]; } ); // Result: “<root id="abc" foo="bar"><bla id="def" foo="bar" /></root>” // Please note that empty tags will always be returned with // a space before the slash.
通过引用修改属性
echo XMLTransformer::transformString( '<root xml:a="a" xml:b="b" id="foo">Content</root>', function($tag, &$attributes, $opening) { foreach ($attributes as $name => $value) { if ('xml:' === substr($name, 0, 4)) { unset($attributes[$name]); // Drop attributes in "xml" namespace } } } ); // Result: “<root id="foo">Content</root>”
作者 & 许可证
此代码由Carsten Blüm编写(www.bluem.net)并许可在BSD2许可证下使用。
版本历史
2.0.1 (2020-12-02)
- 修复了当
null
作为XMLTransformer::RULE_TAG
的值返回时的不一致行为(这是不应该做的)。 - 仅作记录:在PHP8上测试成功运行(尚未在
.travis.yml
中,因为Travis CI尚不支持PHP 8)。
2.0 (2018-02-12)
- BC中断:最小PHP版本为7.0
- BC中断:引入了用于转换规则的类常量,应使用这些常量而不是版本1中使用的魔法字符串。这意味着,在你的代码中,你应该……
- 将字符串
insend
更改为XMLTransformer::RULE_ADD_END
- 将字符串
insafter
更改为XMLTransformer::RULE_ADD_AFTER
- 将字符串
insbefore
更改为XMLTransformer::RULE_ADD_BEFORE
- 将字符串
insstart
更改为XMLTransformer::RULE_ADD_START
- 将字符串
transformInner
修改为XMLTransformer::RULE_TRANSFORM_INNER
- 将字符串
transformOuter
修改为XMLTransformer::RULE_TRANSFORM_OUTER
- 将字符串
tag
修改为XMLTransformer::RULE_TAG
- 将字符串
- BC 兼容性中断:常量
XMLTransformer::ELOPEN
被重命名为XMLTransformer::ELEMENT_OPEN
,XMLTransformer::ELEMPTY
被重命名为XMLTransformer::ELEMENT_EMPTY
,以及XMLTransformer::ELCLOSE
被重命名为XMLTransformer::ELEMENT_CLOSE
。 - 代码简化,现代化
1.2 (2015-12-05)
- 添加了处理 CDATA 的缺失支持。默认情况下,CDATA 部分会被保留,但通过将
transformString()
的第三个参数设置为 false,CDATA 内容将被替换为 PCDATA 内容,其中<
、>
和&
被转义。
1.1 (2015-08-15)
- 回调函数/方法/闭包可以通过引用接收属性。参见上文的“通过引用传递属性”。
- PHP 5.3 兼容性修复
1.0 (2012-12-12)
- 第一个公开版本