xml_set_character_data_handler

(PHP 4, PHP 5, PHP 7, PHP 8)

xml_set_character_data_handler设置字符数据处理程序

描述

xml_set_character_data_handler(XMLParser $parser, callable $handler): true

为 XML 解析器 parser 设置字符数据处理程序函数。

参数

parser

XML 解析器。

handler

如果传递 null 或空字符串,则处理程序将重置为其默认状态。

如果 handler 是一个 callable,则可调用对象将设置为处理程序。

如果 handler 是一个 string,它可以是使用 xml_set_object() 设置的对象的方法名。

处理程序的签名必须为

handler(XMLParser $parser, string $data): void
parser
调用处理程序的 XML 解析器。
data
字符数据,以字符串形式。

字符数据处理程序将为 XML 文档中的每一段文本调用。它可以在每个片段内部被多次调用(例如,对于非 ASCII 字符串)。

返回值

始终返回 true

变更日志

版本 描述
8.0.0 parser 现在需要一个 XMLParser 实例;以前,需要一个有效的 xml resource
添加备注

用户贡献的备注 9 备注

up
2
flobee
19 年前
关于 Philippe Marc 和 karuna_gadde 的示例

我发现 xml_set_character_data_handler 回调函数可以更频繁地为同一个元素调用,尤其是在内容很短的情况下(发生在 Windows 上)。

因此,进行检查可以给你答案,可能对于长字符串也是如此。
例如
<?php
xml_set_character_data_handler
($this->parser, "cdata");
//...
function cdata($parser, $cdata) {
// ...
if(isset($this->data[$this->currentItem][$this->currentField])) {
$this->data[$this->currentItem][$this->currentField] .= $cdata;
} else {
$this->data[$this->currentItem][$this->currentField] = $cdata;
}
?>
up
2
jhill at live dot com
15 年前
为了检测数据连接是否正在进行,你可以跟踪上一次函数调用是否为数据处理函数。
例如,使用下面的 $this->inside_data 变量

<?php
xml_set_element_handler
($this->parser, "start_tag", "end_tag");
xml_set_character_data_handler($this->parser, "contents");

protected function
contents($parser, $data)
{
switch (
$this->current_tag) {
case
"name":
if (
$this->inside_data)
$this->name .= $data; // 需要连接数据
else
$this->name = $data;
break;
...
}
$this->inside_data = true;
}

protected function
start_tag($parser, $name)
{
$this->current_tag = $name;
$this->inside_data = false;
}

protected function
end_tag() {
$this->current_tag = '';
$this->inside_data = false;
}
?>
up
1
ben at removethis emediastudios dotcom
19 年前
我也很喜欢未记录的“拆分”功能 :-p。

我建议不要根据当前标签名称是否与上一个标签名称不同来连接数据,而是像下面这样始终连接,并在 endElement 函数中取消设置 $catData 变量。

<?php

function endElement ($parser, $data) {
global
$catData;

// 因为我们处于元素结束位置,所以我们知道任何拆分都已完成
unset($GLOBALS['catData']);
}

function
characterData ($parser, $data) {
global
$catData;

// 连接数据,以防出现拆分情况
$catData.=$data;

}

?>

这帮我解决了一个问题,因为对于空标签,characterData 不会被调用,所以即使没有发生拆分,上一个和当前标签名称也是相同的。

<companydept>
<companydeptID></companydeptID>
<companyID>1</companyID>
<companydeptName></companydeptName>
</companydept>
<companydept>
<companydeptID></companydeptID>
<companyID>2</companyID>
<companydeptName></companydeptName>
</companydept>
<companydept>
<companydeptID></companydeptID>
<companyID>3</companyID>
<companydeptName></companydeptName>
</companydept>
up
1
unspammable-iain at iaindooley dot com
18 年前
关于下面 jason at omegavortex dot com 的内容,处理空白问题的一种方法是

function charData($parser,$data)
{
$char_data = trim($data);

if($char_data)
$char_data = preg_replace('/ */',' ',$data);

$this->cdata .= $char_data;
}

这意味着

<p>这是我的文本 <a href="something">我的文本</a>
这里还有一些文本,在行首有一些空格
的开头</p>

可以正确显示。如果你想处理文件中的制表符,你可以进行进一步的替换。我始终只使用空格。如果你只使用 trim(),那么你将在上面的 <a> 标签之前丢失空格,但 trim() 是检查完全为空的字符数据的好方法,然后只需将多个空格替换为单个空格。这将保留字符数据开头和结尾的单个空格。
up
1
yaroukh at email dot cz
19 年前
如果有人能完成这个函数的文档,那就太好了。我认为“拆分”行为应该(至少)在文档中提及,如果没有解释(请!)。我不确定切分是在每 1024 字节/字符数据之后进行的。

我的经验如下
[xmlFile]
...
<label>slo|?ka</label>
<comment>koment|?&#345; slo?ky</comment>
...
[/xmlFile]
(字符数据被拆分的地方用管道符号标记。另外,还有带有变音符的拉丁小写字母 'r' 而不是 &#345;。)

由于文档中没有提到拆分,因此可以认为这是一个错误;特别是当你使用 UTF-8 时,切分正好出现在一些特殊字符之前。
($cData 的连接是否应该被认为是处理字符数据的正确和“最终”方法?)

此外,我建议在 "Description" 中添加另一行,说明当 fc 具有备用用法时(而不是将其隐藏在 "Note" 中:o);在这种情况下,我更喜欢这样

描述
bool xml_set_character_data_handler ( resource parser, callback handler )
bool xml_set_character_data_handler ( resource parser, object reference, method name )

... 当然,有数十个函数的文档都是这样做的(我的意思是,没有在 "Description" 部分中提及备用用法)。

祝您有美好的一天
Yaroukh
up
1
Philippe Marc
19 年前
如何覆盖 xml_set_character_data_handler 的 1024 个字符限制。
我花了一些时间才弄清楚如何处理这个问题!

调用基本 XML 解析器时
$parseurXML = xml_parser_create();
xml_set_element_handler($parseurXML, "opentagfunction", "closetagfunction");
xml_set_character_data_handler($parseurXML, "textfunction");

textfunction 每次只接收 1024 个字符,即使文本有 4000 个字符长。事实上,解析器似乎将数据拆分成 1024 个字符的片段。处理方法是将它们连接起来。

示例
如果你有一个名为 UNIPROT_ABSTRACT 的 XML 标签,其中包含 4000 个字符的蛋白质描述
function textfunction($parser, $text)
{
if ($last_tag_read=='UNIPROT_ABSTRACT') $uniprot.=$text;
}
该函数被调用 4 次,并接收 1024+1024+1024+928 个字符,这些字符将使用 ".=" 连接函数连接到 $uniprot 变量中。

很容易做到,但没有文档!
up
1
Brad dot Harrison at griffith dot edu dot au
20 年前
如果你需要修剪 HTML 代码中的空白,并且不依赖于空白来格式化文本(如果依赖于空白来格式化文本,那么现在应该使用样式表),那么这段代码会非常有用。

$data=eregi_replace(">"."[[:space:]]+"."<","><",$data);
$data=eregi_replace(">"."[[:space:]]+",">",$data);
$data=eregi_replace("[[:space:]]+"."<","<",$data);
up
1
dan30odd08 at hotmail dot com
20 年前
我只想提一下,我在使用字符数据处理程序解析 XML 文件时遇到了一个问题。如果你碰巧在你的 XML 数据文件中存储了一个字符串,该字符串也是一个内部 PHP 函数,并且你想要将其输出为字符串,解析器似乎无法识别它。
我找到了解决这个问题的方法。在我的案例中,我存储了一个带有读取值的字符串。这将不允许我输出数据,为了解决这个问题,我在数据元素中的每个字符前面添加了一个反斜杠。

例如 <xml>
从 <element>read</element>
到 <element>////read</element>

我不知道是否有人遇到过这个问题,但我认为我应该把它写在这里,以防有人遇到同样的问题。
up
1
ken at positive-edge dot com
22 年前
当解析字符数据时,函数处理程序会被调用多次。它不会像建议的那样返回整个字符串。有一些特殊的例外情况会始终强制解析器停止扫描并调用字符数据处理程序。这是在

- 解析器遇到实体声明,例如 &amp; (&) 或 &apos; (?)
- 解析器完成解析实体
- 解析器遇到换行符 (\n)
- 解析器遇到一系列制表符 (\t)

以及其他情况。

例如,如果我们有以下 xml 内容

<mytag name=?Ken Egervari? title=?Chief Technology Officer?>
Ken has been Positive Edge&apos;s Chief Technology Officer for 2 years.
</mytag>

解析器将调用字符数据处理程序 6 次。这是将要发生的事情

1 \n
2 \t
3 Ken has been Positive Edge
4 ?
5 s Chief Technology Officer for 2 years.
6 \n

希望这能帮助大家。
To Top