1

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

<?xml:namespace prefix = o /?>

如何使用 PHP 和正则表达式从字符串中删除该标签和类似标签?

我试过了:

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

使用 Knedo 数据源/网格进行分组

如何在 Kendo Grid/Datasource 中完成此操作?

我有看起来像这样的数据:

Month | Value
--------------
1     |  10
1     |  15
1     |  30
2     |  5
2     |  7
3     |  4

我想按月对这些数据进行分组,并以这种形式将其输出到网格中:

Month | Sum(Value)
------------------
1     |  55
2     |  12
3     |  4

我不想要任何组标题和带有项目的可折叠组,我只想要那个简单的输出。

我怎么能在剑道中做到这一点?

4

2 回答 2

1

您在该字符串中拥有的是处理指令(PI,请参阅 XML 1.0)

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

~
    <\?
    (?: [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 ) )

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

正则表达式的替代品

strip_tags首先,使用 PHP来剥离处理指令会容易得多。它也会删除其他标签和评论。这可能并不总是想要的,它真的很简单:

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 解析器不会让您处理浅层解析。

于 2015-04-03T01:17:31.003 回答
0

你非常接近 - 注意'?在右尖括号之前的最后:

<?xml:namespace prefix = o /?>

为了匹配它,你将需要这个:

<?php
$clean=preg_replace('/<\?xml[^>]+\/\?>/im', '', $dirty);
?>
于 2015-04-02T17:23:29.697 回答