从 XML 字符串中删除处理指令(<?xml 标记和内容)



我在字符串中有这个标签:

<?xml:namespace prefix = o /?>

如何使用PHP和regex从字符串中删除该标记和类似的标记?

我试过了:

$clean = preg_replace('/<?xml[^>]+/>/im', '', $dirty);

该字符串中有一个处理指令(PI,请参阅XML 1.0)。

如果您想从一个字符串中删除那些PI,而您希望该字符串是UTF-8编码的,而不使用PCRE UTF-8修饰符,您可以使用以下模式:

~
    <?
    (?: [A-Za-z_:] | [^x00-x7F] ) (?: [A-Za-z_:.-] | [^x00-x7F] )*
    (?: ?> | s (?: [^?]* ?+ ) (?: [^>?] [^?]* ?+ )* >)
~x

它是从XML处理指令的REX表达式到PHP中使用的PCRE表达式的转换。

代码示例:

$str = "some string <?xml:namespace prefix = o /?> that is";
$pattern = '~
    <?
    (?: [A-Za-z_:] | [^x00-x7F] ) (?: [A-Za-z_:.-] | [^x00-x7F] )*
    (?: ?> | s (?: [^?]* ?+ ) (?: [^>?] [^?]* ?+ )* >)
~x';
echo preg_replace($pattern, '', $str);

输出:

some string  that is

与前面给出的答案不同的是,这个正则表达式确实。。。

  • 。。。正确考虑关闭顺序("?>")。特别是在处理指令中可以允许使用">"
  • 。。。不需要将处理指令的名称限制为仅以"xml"开头
  • 。。。它实际上是在寻找一个名字作为开头序列的一部分
  • 。。。处理空的和非空的处理指令

关于限制,值得一提的一些注意事项:

  1. 该模式用于浅层解析。也就是说,如果您还没有从可能包含文本的字符串中剥离其他标记构造,而这些文本又可能看起来像这样的处理指令(例如CDATA块或注释),那么模式将错误匹配
  2. 该模式与XML声明匹配,该声明也以"<?xml"开头。这可以通过在打开"<?"后不查找XML保留名称来改变,并使用类似"(?! [xX][mM][lL] (?: ?> | s ) )"的负前瞻

由于这些限制,也许值得考虑

正则表达式的替代项

首先,只使用PHP的strip_tags来剥离处理指令会容易得多。它还将删除其他标签和注释。这可能并不总是想要的,它只是非常直接:

strip_tags($str)

与正则表达式和strip_tags一样,更明确的是使用PHP附带的一个XML解析器来剥离处理指令。例如PHP的DOM扩展。它可以封装在一个函数中,以便轻松地应用于字符串:

dom_strip_pis($str)

这样一个示例性函数也适用于使用保留名称"xml"作为前缀的XML字符串,这在XML中实际上并不正确。但解析器不会被它卡住:

/**
 * remove processing instructions from an XML string
 *
 * @author hakre <http://hakre.wordpress.com>
 *
 * @param string $xml
 * @return string
 */
function dom_strip_pis($str) {
    $doc = new DOMDocument;
    $fragment =  $doc->createDocumentFragment();
    $saved = libxml_use_internal_errors(true);
    $fragment->    appendXML($str);
    libxml_use_internal_errors($saved);
    foreach($fragment->childNodes as $node) {
        if ($node instanceof DOMProcessingInstruction) {
            $node->parentNode->removeChild($node);
        }
    }
    return $doc->saveXML($fragment);
}

使用上一个示例中给出的XML解析器将不需要处理浅解析。

你非常接近-注意到"?"在关闭角括号前的最后:

<?xml:namespace prefix = o /?>

为了匹配,你需要这个:

<?php
$clean=preg_replace('/<?xml[^>]+/?>/im', '', $dirty);
?>

相关内容

  • 没有找到相关文章

最新更新