bluem/xmltransformer

用于将 XML 转换为 XML、HTML、纯文本等的 PHP 库

2.0.1 2020-12-02 17:58 UTC

This package is auto-updated.

Last update: 2024-08-29 03:35:15 UTC


README

Build Status SensioLabsInsight

概述

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_OPENXMLTransformer::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)

  • 第一个公开版本