【问题标题】:PHP REGEX: Remove/replace quotes within an XML attributePHP REGEX:删除/替换 XML 属性中的引号
【发布时间】:2017-05-12 05:38:47
【问题描述】:

请考虑 XML 文件(从第三方来源生成)中的以下行:

<record ObTime="2017-05-10T23:30" data_value="Ocean Park "The Sea WX"  WA US" />

如您所见,data_value 属性在值内包含引用字符串,这会导致 XML 验证器傻笑和爆炸。

任何给定的 XML 文件都可能有数千行。有没有办法将 REGEX 应用于整个文件?而且,用更温和的东西替换引号的 REGEX 会是什么?

【问题讨论】:

    标签: php regex


    【解决方案1】:

    可能还有其他更好的解决方案,但我就是这样做的:

    • 使用preg_match_all 和某些正则表达式来捕获所有 个匹配项,并将它们存储在一个数组$matches[0]中。
    • The regex(?&lt;=data_value=").*(?=" \/&gt;) 将捕获 data_value="" /&gt;) 之间的所有内容,通过使用 positive lookbehind and lookahead,精确匹配 值 每个 data_value 属性。
    • 遍历 $matches[0] 中的项目,我们执行以下操作:
      1. 将每个双引号字符串 " 替换为 % [可以是任何其他字符串,即使是空白,也不会导致进一步的问题]匹配,并将其存储在临时变量$str中。
      2. 然后将整个数据字符串中每个匹配项的值替换为匹配项的修改版本的值,即 $str 字符串。

    PHP 代码:
    请记住,因为数据是 xml 标签,您需要使用“查看源代码”才能看到输出,或者,您可以使用var_dump 而不是echo

    <?php
    $data = '<record ObTime="2017-05-10T23:30" data_value="Ocean Park "The Sea WX"  WA US" />
    <record ObTime="2017-11-10T23:30" data_value="Some Other "Demo Text"  In Here" />';
    
    $data_valueVal = preg_match_all('#(?<=data_value=").*(?=" \/>)#i', $data, $matches);
    
    foreach($matches[0] as $match) {
        $str = str_replace('"', "%", $match);
        $data = str_replace($match, $str, $data);
    }
    echo $data;
    ?>
    

    输出:

    &lt;record ObTime="2017-05-10T23:30" data_value="Ocean Park %The Sea WX% WA US" /&gt; &lt;record ObTime="2017-11-10T23:30" data_value="Some Other %Demo Text% In Here" /&gt;

    【讨论】:

    • 非常感谢。我将在解析之前将其应用于每个文件。
    • 不客气,我很高兴它有帮助.. 享受编码!
    • 对于新的 xml 数据样本,使用这个正则表达式 (?&lt;=data_value=")[^=]+(?=" (?:\w+=)?) Regex Demo 而不是我答案中的那个,它可以同时捕获 data_value 属性
    • 如果您只想捕获第二个 data_value ,请改用 (?&lt;=data_value=")[^=]+(?=" \/&gt;)regex Demo
    【解决方案2】:

    使用下面的正则表达式,您可以分别匹配这些双引号以进行进一步修改:

    (?:="|"\s+(?:\w+="|\/>))(*SKIP)(?!)|"
    

    通过使用(*SKIP)(?!),您可以强制引擎在每次成功匹配后跳过交替的第一侧。

    Live demo

    PHP 代码(去掉引号):

    echo preg_replace('~(?:="|"\s+(?:\w+="|\/>))(*SKIP)(?!)|"~', '', $xml);
    

    【讨论】:

    • 这个不错,以前从没听说过这个(*SKIP)(?!),点赞!
    • 哇... SKIP 很酷。我是 REGEX 的新手,所以对我来说一切都像是魔法……但这是我第一次看到 SKIP。感谢您的回答!
    • @revo,看起来 开始标记中的引号也被捕获。这个演示有更多详细的数据可供查看。 regex101.com/r/toFV9f/4
    • 您可能希望将正则表达式中的\/&gt; 部分更改为[\/?]&gt;
    • @TomSawyer 将 \s+ 更改为 \s*
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    相关资源
    最近更新 更多