gpt4 book ai didi

PHP XML Expat 解析器 : how to read only part of the XML document?

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:09:05 29 4
gpt4 key购买 nike

我有一个具有以下结构的 XML 文档:

<posts>
<user id="1222334">
<post>
<message>hello</message>
<client>client</client>
<time>time</time>
</post>
<post>
<message>hello client how can I help?</message>
<client>operator</client>
<time>time</time>
</post>
</user>
<user id="2333343">
<post>
<message>good morning</message>
<client>client</client>
<time>time</time>
</post>
<post>
<message>good morning how can I help?</message>
<client>operator</client>
<time>time</time>
</post>
</user>
</posts>

我能够创建解析器并打印出整个文档,但问题是我只想打印(用户)节点和具有特定属性(id)的子节点。

我的 PHP 代码是:

if( !empty($_GET['id']) ){
$id = $_GET['id'];
$parser=xml_parser_create();
function start($parser,$element_name,$element_attrs)
{
switch($element_name)
{
case "USER": echo "-- User --<br>";
break;
case "CLIENT": echo "Name: ";
break;
case "MESSAGE": echo "Message: ";
break;
case "TIME": echo "Time: ";
break;
case "POST": echo "--Post<br> ";
}
}

function stop($parser,$element_name){ echo "<br>"; }
function char($parser,$data){ echo $data; }
xml_set_element_handler($parser,"start","stop");
xml_set_character_data_handler($parser,"char");

$file = "test.xml";
$fp = fopen($file, "r");
while ($data=fread($fp, filesize($file)))
{
xml_parse($parser,$data,feof($fp)) or
die (sprintf("XML Error: %s at line %d",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
}
xml_parser_free($parser);
}

start()函数中使用这个可以选择正确的节点,但对读取过程没有任何影响:

    if(($element_name == "USER") && $element_attrs["ID"] && ($element_attrs["ID"] == "$id"))

任何帮助将不胜感激

更新:XMLReader 可以工作,但是当使用 if 语句时它停止工作:

foreach ($filteredUsers as $user) {
echo "<table border='1'>";
foreach ($user->getChildElements('post') as $index => $post) {

if( $post->getChildElements('client') == "operator" ){
printf("<tr><td class='blue'>%s</td><td class='grey'>%s</td></tr>", $post->getChildElements('message'), $post->getChildElements('time'));
}else{
printf("<tr><td class='green'>%s</td><td class='grey'>%s</td></tr>", $post->getChildElements('message'), $post->getChildElements('time'));

}
}
echo "</table>";
}

最佳答案

正如之前评论中所建议的,您也可以使用 XMLReader Docs .

The XMLReader extension is an XML Pull parser. The reader acts as a cursor going forward on the document stream and stopping at each node on the way.

它是一个可以打开文件的类(同名:XMLReader)。默认情况下,您使用 next()移动到下一个节点。然后您将检查当前位置是否在某个元素处,然后该元素是否具有您要查找的名称,然后您可以处理它,例如通过读取元素的外部 XML XMLReader::readOuterXml() Docs .

与Expat解析器中的回调相比,这有点累赘。使用 XMLReader 获得更大的灵 active 我通常自己创建 iterators that are able to work on the XMLReader object and provide the steps I need .

它们允许直接使用 foreach 遍历具体元素.这是这样一个例子:

require('xmlreader-iterators.php'); // https://gist.github.com/hakre/5147685

$xmlFile = '../data/posts.xml';

$ids = array(3, 8);

$reader = new XMLReader();
$reader->open($xmlFile);

/* @var $users XMLReaderNode[] - iterate over all <user> elements */
$users = new XMLElementIterator($reader, 'user');

/* @var $filteredUsers XMLReaderNode[] - iterate over elements with id="3" or id="8" */
$filteredUsers = new XMLAttributeFilter($users, 'id', $ids);

foreach ($filteredUsers as $user) {
printf("---------------\nUser with ID %d:\n", $user->getAttribute('id'));
echo $user->readOuterXml(), "\n";
}

我已经创建了一个 XML 文件,其中包含您问题中的更多帖子,编号在 id 中一个及以上的属性:

$xmlFile = '../data/posts.xml';

然后我创建了一个数组,其中包含用户感兴趣的两个 ID 值:

$ids = array(3, 8);

稍后会在过滤条件中使用。然后 XMLReader创建并打开 XML 文件:

$reader = new XMLReader();
$reader->open($xmlFile);

下一步创建一个遍历所有 <user> 的迭代器该阅读器的元素:

$users = new XMLElementIterator($reader, 'user');

然后过滤为 id先前存储到数组中的属性值:

$filteredUsers = new XMLAttributeFilter($users, 'id', $ids);

其余的正在迭代 foreach现在所有条件都已制定:

foreach ($filteredUsers as $user) {
printf("---------------\nUser with ID %d:\n", $user->getAttribute('id'));
echo $user->readOuterXml(), "\n";
}

这将返回 ID 为 3 和 8 的用户的 XML:

---------------
User with ID 3:
<user id="3">
<post>
<message>message</message>
<client>client</client>
<time>time</time>
</post>
</user>
---------------
User with ID 8:
<user id="8">
<post>
<message>message 8.1</message>
<client>client</client>
<time>time</time>
</post>
<post>
<message>message 8.2</message>
<client>client</client>
<time>time</time>
</post>
<post>
<message>message 8.3</message>
<client>client</client>
<time>time</time>
</post>
</user>

XMLReaderNode这是 the XMLReader iterators 的一部分也提供了 SimpleXMLElement Docs如果您想轻松读取 <user> 中的值元素。

以下示例显示如何获取 <post> 的计数<user> 内的元素元素:

foreach ($filteredUsers as $user) {
printf("---------------\nUser with ID %d:\n", $user->getAttribute('id'));
echo $user->readOuterXml(), "\n";
echo "Number of posts: ", $user->asSimpleXML()->post->count(), "\n";
}

这将显示 Number of posts: 1对于用户 ID 3 和 Number of posts: 3对于用户 ID 8。

但是,如果外部 XML 很大,您不想这样做,而是想继续在该元素内部迭代:

// rewind
$reader->open($xmlFile);

foreach ($filteredUsers as $user) {
printf("---------------\nUser with ID %d:\n", $user->getAttribute('id'));
foreach ($user->getChildElements('post') as $index => $post) {
printf(" * #%d: %s\n", ++$index, $post->getChildElements('message'));
}
echo "Number of posts: ", $index, "\n";
}

产生以下输出:

---------------
User with ID 3:
* #1: message 3
Number of posts: 1
---------------
User with ID 8:
* #1: message 8.1
* #2: message 8.2
* #3: message 8.3
Number of posts: 3

此示例显示:根据嵌套子项的大小,您可以使用 getChildElements() 提供的迭代器进一步遍历或者您也可以使用常见的 XML 解析器,如 SimpleXML甚至 DOMDocument在 XML 的子集上。

关于PHP XML Expat 解析器 : how to read only part of the XML document?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15423594/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com