Frage

Ich versuche, bestimmte Tags mit ihren Inhalten aus einem XHTML -Dokument abzurufen, aber es stimmt mit den falschen End -Tags überein.

Im folgenden Inhalt:

<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>

Das Content_Block Ending -Tag für ID = "Welcome" wird tatsächlich als End -Tag des ersten Öffnungs -Content_Block -Tags angepasst.

Die Regex, die ich benutze, ist:

/<content_block id="(.*)">([\w\W]*?)<\/content_block>/i

Irgendwelche Hinweise darauf, wo ich versage?

War es hilfreich?

Lösung

… Und die Antwort ist immer die gleiche: HTML + Regex kann nicht durchgeführt werden. Es tut uns leid. Verwenden Sie eine HTML -Parsing -Bibliothek für Ihr spezielles Framework. Wenn Ihr Dokument garantiert nur gültige XHTML enthält, nehmen Sie den von Jitter vorgeschlagenen XPath -Ansatz in einem Kommentar vor.

Andere Tipps

Dies könnte helfen, ein Tutorial zu finden http://www.regular-expressions.info/examples.htmlWelches erwähnt, dass ein Stringpaar in gegebenem Text wiederholt wird. Vorschlag ist zu verwenden? Nach.* Um es nach dem ersten Auftreten der Endzeichenfolge des Paares im Text zu stoppen

Dies ist ein bekanntes Problem mit Regex - Sie können keine Paare übereinstimmen. Das Matching ist entweder gierig, in dem es dem zuletzt entspricht, den es findet, oder nicht Greedy, in dem es dem ersten passt. Sie können einen Regex nicht davon überzeugen, das Öffnen und Schließen von Klammern zu zählen.

Ich würde empfehlen, es in ein DOM zu laden und das zu verwenden. Wenn Sie versuchen, einen HTML-Parser zu implementieren, würde ich empfehlen, REGEX zu verwenden, um es zu verwenden, und dann ein links-Rechts-Parser, um die Ausgabe Ihres Lexer zu analysieren.

Dank an @Jan żankowski und @ikegami, ihre Antwort gab mir Inspiration

Lassen Sie mich PHP verwenden, um den Code zu demonstrieren

<?php
$xml = <<<EOT
<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
EOT;

preg_match('/<cache_namespace[^>]+>((?:(?!(<\/?div>)).)*)<\/cache_namespace>/s', $xml, $matches);
print_r($matches);

Regex -Note

  • s Option: a . Im Muster passt alle Charaktere, einschließlich Newlines, überein
  • Der Schlüssel hier ist das (?:(?!STRING).)* ist Strings als [^CHAR]* ist für Charaktere

Ergebnis

Array
(
    [0] => <cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
    [1] => 
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>

)

Das Parsen von XHTML oder XML ist nicht schwer. Ich nahm an, dass Sie einen gültigen oder gut geformten Code haben.

#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
my $xml = <<"EOF";
<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
EOF

while ($xml =~ m!
<(content_block)\sid="welcome"> # Start tag definition.
 (\s*                           # It may consists of
   (?: <\!--.*?-->              # - comment
   |  [^<]*                     # - text
   |  <[^>]+/>                  # - another closed tag
   |  <\s*(\w+)[^>]*>           # - another tag with some content
       (?2)+                    # (recursive definition of possible tag content)
      </\3>
   )
 )*
</\1>
!sxgc) {
    print "==> $&\n\n";
}

Bitte ändern Sie die Start -Tag -Definition für einen anderen Inhalt (wie wie <\s*(\w+)[^>]*+>). Wie auch immer, es ist ein guter Startpunkt.

Wenn Sie keine Rekursion verwenden (Linie mit (?2)+) Sie werden festhalten Solche Beispiele. Dieser Code kann sie alle verarbeiten (bitte schauen Sie hier vorher) oder kann sich leicht für neue Situationen anpassen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top