正则表达式在使用php和simplexml_load_string解析失败时用xml标记冒号
在我的last question的后续内容中,如果您有一个xml文件格式错误的字符串,可以使用preg_replace_callback()提取内容以删除破坏的元素。正则表达式在使用php和simplexml_load_string解析失败时用xml标记冒号
此功能的点不与正则表达式解析XML(一坏主意 ),而是试图找到XML不解析和它失败,使我们能 标志物品在发送出 之前没有正确格式化。这是在发送 之前清除内容的一组工具中的一部分。我正在测试它在已知格式不正确的公开RSS网址上,以及 作为内部网址来查看它是否适合多种情况。该回调将为失败的节点返回一个整数。如果在此之后通过,我们可以报告文章的索引,然后尝试使用DOMDocument尝试更正html并重试。如果失败,我们将它作为一个重要的报告,否则,我们返回解析文章描述和内容回数据库,将其标记为分娩前进行修改。
然后,您可以取出损坏的元素,并通过DOMDocument运行它们以更好地格式化它们以返回到XML文件。
但是,我坚持就如何使下面false以外回报这个例子:
示例XML:
<item>
<content:encoded><![CDATA[
This is the text with odd characters that are killing
simplexml_load_string() (doesn't recover) and breaking
(although recoverable) DOMDocument
]]></content:encoded>
</item>
如果我用下面的PHP,我可以提取描述节点
<description><![CDATA[
This is some description text with the same problem
]]></description>
到
<description>0</description>
:从将其转换
PHP:
preg_replace_callback(
'/<description>(.*)<\/description>/', **// add msU modifiers to fix below**
'node_tidy::callback_description',
$xml
);
...
private function callback_description($matches=false) {
if(false !== $matches) {
$this->arrDescriptions[] = $matches[1];
return '<description>'.$this->indexDescriptions++.'</description>';
} else {
return false;
}
}
然而,当我尝试做相同的content:encoded
节点,则返回false。下面是相关的函数:
private function callback_content_encoded($matches=false) {
if(false !== $matches) {
$this->arrContentEncoded[] = $matches[1];
return '<content:encoded>'.$this->indexContentEncoded++.'</content:encoded>';
} else {
return false;
}
}
使用直正则表达式,以测试它的冒号,我用这个:
<?php
$string = '<content:encoded>this is some text</content:encoded>';
preg_match('/<content\:encoded>(.*)<\/content\:encoded>/',$string,$matches);
echo '<pre>';
print_r($matches);
echo '</pre>';
?>
然而,这并没有添加或不添加\:
打印预期阵列。可能有人点我在这里认识误区正确的方向?
非常感谢!
UPDATE: 这里的失败,通过@Florent指示的真正的XML的示例代码段。
UPDATE: 此正则表达式所需的内容相匹配:
preg_match('/<content\:encoded>(.*)<\/content\:encoded>/msU',$string,$matches);
的M和S和U修饰符解释的更好位置: http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
我不想去考虑这些修饰语。
结果现在带回了这个正则表达式,包括原始问题,所以现在可以解决。
您应该添加以下标志您正则表达式:
-
m
,使多串 -
u
启用UTF8字符串(如有必要)
谢谢:)) - 特别是,我发现m和u对于使用CDATA包装从畸形xml节点获取xml内容至关重要。发现。 – MyStream 2012-07-09 16:22:24
多行修饰符是不被使用,所以它不需要。只有/ s(点全部)修饰符是必要的。永远不要使用/ U(非贪婪)修饰符(在我看来)。应该使用/ u(unicode)修饰符。
如果您正在寻找解开CDATA结构内的html,最好使用w3c规范,即使您的xml使用其标记的命名空间名称。这只有在xml标签中唯一的元素是CDATA的时候,并且假定xml格式良好。
在现实世界中,评论可能包装CDATA,反之亦然,同时隐藏很多其他的东西。所以,现实是正则表达式可能能够通过错误的xml解析然后恢复,但是它不可靠,而且肯定更复杂。
这就是说,这将从您的示例中提取CDATA,并仅从字面意义上提取CDATA。
if (preg_match(
'~<content:encoded\s*>
\s*
<!\[CDATA\[ (.*?) \]\]>
\s*
</content:encoded\s*>~xsu',
$string,
$matches))
{
print ($matches[1]);
}
嗨,我们发现一些xml(没有内容编码和描述节点)格式良好,但不会与地方的那些节点解析,即使它正确包装了CDATA。通过删除那些元素(所有内容)然后尝试重新分析,我们可以继续。然后我们可以通过一些检查运行提取内容,包括首先使用DOMDocument清理html,并确保实体在这些内容中转义并将其放回。这远非理想,但似乎有助于纠正大部分问题。为什么你不使用/ U,具体? – MyStream 2012-07-11 19:25:33
第二次Downvote没有任何解释。谨慎解释为什么我可以相应地调整问题? – MyStream 2012-07-09 15:12:29
为什么你说,_your正则表达式不打印预期array_?我试了一下,得到了节点内容。 – Florent 2012-07-09 15:18:25
也许我的用例太窄了 - 我会发布我想要解析的确切字符串,也许答案就在那里。请再检查一次? – MyStream 2012-07-09 15:21:52