【问题标题】:Regular expression to match ">", "<", "&" chars that appear inside XML nodes正则表达式匹配出现在 XML 节点中的“>”、“<”、“&”字符
【发布时间】:2011-01-17 23:08:59
【问题描述】:

我正在尝试使用 PHP 中的 PCRE 库编写正则表达式。

我需要一个正则表达式来匹配任何 XML 节点的字符串部分中存在的 &amp;&gt;&lt; 字符,而不是标签声明本身。

输入 XML:

<pnode>
  <cnode>This string contains > and < and & chars.</cnode>
</pnode>

这个想法是搜索和替换这些字符并将它们转换为 XML 实体等价物。

如果我要将整个 XML 转换为实体,XML 将如下所示:

整个 XML 转换为实体

&lt;pnode&gt;
  &lt;cnode&gt;This string contains &gt; and &lt; and &amp; chars.&lt;/cnode&gt;
&lt;/pnode&gt;

我需要它看起来像这样:

正确的 XML

<pnode>
  <cnode>This string contains &gt; and &lt and &amp; chars.</cnode>
</pnode>

我曾尝试编写一个正则表达式来使用look-aaead 匹配这些字符,但我不知道如何让它工作。我的尝试(目前只尝试匹配 > 符号):

/>(?=[^<]*<)/g

只是为了说明我正在尝试修复的 XML 来自第 3 方,他们似乎无法最终修复它,因此我尝试修复它。

【问题讨论】:

  • @Rowland,虽然我同意你的观点,但这正是他想要通过转义 >, < 来获取输入并使其变为有效 XML 的观点。和&字符。
  • 除非你定义了一个模式,否则你怎么可能知道任何给定的
  • 为什么有无效的 XML 开头?是否有可能避免生成格式错误的 XML,而不是在事后尝试修复它?
  • @Camsoft,您是否尝试过将regexlib.com 作为此类事情的资源。如果不是最终解决方案,它可能会提供一些线索。
  • @Camsoft,“值得注意的是,我从第 3 方获取 XML 提要并且无法控制其数据。”不,你会得到一个数据馈送。它不是 XML 提要。如果您的第 3 方说是,他在销售有缺陷的商品。

标签: php xml regex


【解决方案1】:

最后我选择在 PHP 中使用Tidy 库。我使用的代码如下所示:

  // Specify configuration
  $config = array(
    'input-xml'  => true,
    'show-warnings' => false,
    'numeric-entities' => true,
    'output-xml' => true);

  $tidy = new tidy();
  $tidy->parseFile('feed.xml', $config, 'latin1');
  $tidy->cleanRepair()

这可以完美地纠正所有编码错误并将无效字符转换为 XML 实体。

【讨论】:

  • 不要忘记接受你的答案,即使是你,它已经回答了你的问题,并且会避免其他人翻阅其他答案。
【解决方案2】:

垃圾进垃圾出的经典例子。真正的解决方案是修复损坏的 XML 导出器,但显然这超出了您的问题范围。听起来您可能必须手动解析 XML,在内容上运行 htmlentites(),然后放回 XML 标记。

【讨论】:

  • 或 htmlspecialchars() 如果您只想转换提到的字符。
  • XML 由第三方提供,我无法控制数据。 XML 中的字符实体也比 PHP 少,因此 htmlentites() 会过度实体化! ;-)
  • 将其解析为对象的问题是我要修复的实际 XML 文档为 5MB 和 42,000 行。我希望正则表达式能够快速搜索并替换无效字符。
【解决方案3】:

我有理由确定这根本不可能。您需要跟踪嵌套的东西,并且没有办法让正则表达式来跟踪嵌套。您的选择是首先修复文本(当您可能可以使用 RE 时)或使用至少有点像 XML 解析器的东西,特别是在跟踪标签嵌套方式的范围内。

XML 要求这些字符被转义是有原因的——否则,您只能猜测某物是否真的是标签。例如,给定以下内容:

    <tag>Text containing < and > characters</tag>

你和我可能猜到结果应该是:...containing &amp;lt; and &amp;gt;... 但我很确定 XML 规范允许额外的空格,所以正式地“”应该被视为一个标签。我想你可以假设任何看起来像不匹配的标签的东西真的不打算成为标签,但这也需要一些工作。

【讨论】:

  • 是的,我开始这么认为。我越看这个问题,它似乎就越复杂。我只是希望能够避免使用 XML 解析器作为我正在尝试修复的巨大 XML 文件。
【解决方案4】:

是否可以在文本尝试成为 XML 的一部分之前对其进行拦截?几盎司的预防可能抵得上几磅的治疗。

【讨论】:

  • 我不是 XML 的作者,我只是尝试使用它的人。
  • @Camsoft 你会给你的车加满汽油会破坏引擎吗?如果答案是否定的,那么为什么要使用损坏的 XML?告诉提供商修复它。
  • @Gorden,感谢您的回复,尽管这个问题是在一年前提出的!提供商拒绝修复它,显然我尝试过,但除了尝试自己修复之外,我无能为力。
【解决方案5】:

这应该适用于&符号:

/(\s+)(&)(\s+)/gim

这意味着您只在两边都有空白字符时才查找这些字符。

只要确保替换表达式是“$1$2amp;$3”;

其他人会这样,他们的替换表达式在右边

/(\s+)(>)(\s+)/gim   "$1&gt;$2"
/(\s+)(<)(\s+)/gim   "$1&lt;$2"

【讨论】:

  • 这很接近,但是当字符周围没有空格时它不起作用。
  • 您是否希望在字符周围没有空格时使用它?如果添加该功能,您将替换所有 XML 尖括号和 &实体。
  • 是的,我知道。这就是我最初的问题。
【解决方案6】:

正如其他人所说,正则表达式不适用于分层数据。此外,如果数据格式不正确,您不能保证您会得到正确的数据。考虑:

<xml>
    <tag>Something<br/>Something Else</tag>
</xml>

&amp;lt;br/&amp;gt; 应该读作&amp;lt;br/&amp;gt; 吗?没有办法知道,因为它是有效格式的 XML。

如果您希望在 XML 树中包含任意数据,请考虑改用 &lt;![CDATA[ ... ]]&gt; 块。它被视为文本节点,唯一不必转义的就是字符序列]]&gt;

【讨论】:

    【解决方案7】:

    你所拥有的当然不是 XML。在 XML 中,字符 '”可以出现在文本中,但作为字符串“]]>”的一部分除外。在格式良好的 XML 中,文字“

    如果源包含类似 '

    Name ::= NameStartChar (NameChar)*

    那么你的问题就更大了。您将不得不(尝试)解析您的输入,就好像它是真正的 XML 一样,并检测格式错误的名称、不匹配的开始和结束标记、格式错误的属性和未定义的实体引用(仅举几例)的错误情况.不幸的是,不能保证错误情况发生在错误的位置。

    您最好的选择可能是使用 RE 来捕获 90% 的错误并手动修复其余部分。您需要查找 '

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 2014-10-14
      • 1970-01-01
      • 2012-06-23
      • 2011-01-02
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      相关资源
      最近更新 更多