【问题标题】:PHP regex, tag which is not in another tagPHP正则表达式,不在另一个标签中的标签
【发布时间】:2017-09-06 07:55:07
【问题描述】:

我需要一个与<cherry> 标记的内容相匹配的正则表达式,该标记不是另一个标记的一部分。不满意我不能使用 PHP DOM Parser,因为标签的内容有时包含非常特殊的字符。

这是传入输入的示例:

<cherry>test</cherry>
<banana>
    <cherry>test</cherry>
    some text
</banana>

这是我当前的正则表达式,但它也会匹配 &lt;banana&gt; 标签内的 &lt;cherry&gt; 标签

 (<cherry>)(.*?)(<\/cherry>)

如何排除其他标签中的出现?

我已经尝试了很多......

【问题讨论】:

  • 你想得到最上面的cherry标签吗?使用 DOM,会更容易。
  • 嗨,Wiktor,谢谢您的回复。我需要第一个 标签的内容,它不是另一个标签(如 标签的一部分)。我不能使用 dom 解析器,因为我在完整的字符串中有很多特殊字符。
  • 为什么在使用 DOM 时会出现特殊字符问题,这些字符是什么?你能出示一份你的真实文件样本吗?
  • 可能的内容如下所示: A = \bigl\{ (x, y) \in \R \times \R \ | \x^2 + y^2 B = \bigl\{ (x, y) \in \R \times \R \ | \ (x-a)^2 + (y-b)^2 Für welche Werte von a und b sind die Mengen '''A''' und '''B''' [[Durchschnittsmenge|disjunkt]]? '''Hinweis:''' Betrachten Sie das Problemgeometrisch.

标签: php regex


【解决方案1】:

为什么不使用DOMDocument 类而不是正则表达式。只需加载您的 DOM,然后使用getElementsByTagName 来获取您的标签。通过这种方式,您可以排除任何其他您不想要的标签,而只获取您想要的标签。

示例

<?php
$xml = <<< XML
<?xml version="1.0" encoding="utf-8"?>
<books>
 <book>Patterns of Enterprise Application Architecture</book>
 <book>Design Patterns: Elements of Reusable Software Design</book>
 <book>Clean Code</book>
</books>
XML;

$dom = new DOMDocument;
$dom->loadXML($xml);
$books = $dom->getElementsByTagName('book');
foreach ($books as $book) {
    echo $book->nodeValue, PHP_EOL;
}
?>

阅读材料

DOMDocument

【讨论】:

    【解决方案2】:

    假设您只需要顶级数学标签的内容而没有其他任何东西,但到目前为止您还不能这样做,因为数学标签包含无效的 xml,因此任何 xml-parser 都放弃了......(如问题和cmets所述)

    干净的方法可能是,使用一些容错的 xml 解析器(或容错模式)或在之前整理输入。但是,这些方法都可能“破坏”内容。

    hacky 和可能肮脏的方法如下,这很可能有其他问题,尤其是如果剩余的 xml 也是无效的或者你的数学标签是嵌套的(这将导致 xml-parser 在步骤 2 中失败):

    1. 通过preg_replace_callback 或其他东西将任何&lt;math&gt;.*&lt;/math&gt;(不贪心)替换为占位符(最好是独特的uniqid 可能会有所帮助,但一个简单的计数器可能就足够了)
    2. 使用通用 xml 解析器解析文档(根据需要将其包装在一些根标签中)
    3. 获取根节点的所有子节点/所有根节点,查看步骤1中生成了哪些。

    例如:

    <math>some invalid xml</math>
    <sometag>
        <math>more invalid xml</math>
        some text
    </sometag>
    

    替换为

    $replacements = [];
    $newcontent = preg_replace_callback(
           '/'.preg_quote('<math>','/').'(.*)'.preg_quote('</math>','/').'/siU',  
           function($hit) use ($replacements) { 
               $id = uniqid();
               $replacements[$id] = $hit[1];
               return '<math id="'.$id.'" />';
           },
           $originalcontent);
    

    这会将您的内容变成:

    <math id="1stuniqid" />
    <sometag>
        <math id="2nduniqid" />
        some text
    </sometag>
    

    现在使用您选择的 xml 解析器并选择所有根级别/基础级别元素并查找 /math/@id(我的 XPath 可能只是错误,根据需要进行调整)。结果应包含所有 uniqid,您可以在替换数组中查找它们

    编辑:修复了一些preg_quote 问题并使用了更多标准分隔符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-31
      • 1970-01-01
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多