Domanda

Ho un output XML abbastanza grande da un'applicazione. Devo elaborarlo con il mio programma e quindi restituirlo al programma originale. Ci sono pezzi in questo XML che devono essere compilati e sostituiti. La parte interessante si presenta così:

<sys:customtag sys:sid="1" sys:type="Processtart" />
    <sys:tag>value</sys:tag>
    here are some other tags
    <sys:tag>value</sys.tag>
<sys:customtag sys:sid="1" sys:type="Procesend" />

e il documento contiene diversi pezzi come questo.

Devo inserire tutti i pezzi XML all'interno di questi tag per poterlo modificare. Ho scritto un'espressione regolare per ottenere quei pezzi ma non funziona:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(@"output.xml");
Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>", RegexOptions.Multiline & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant);
MatchCollection matches = regExp.Matches(xmlDoc.InnerXml);

Se lascio l'intera roba su una riga e chiamo questa regexp senza l'opzione multilinea, trova tutte le occorrenze. Lasciando il file così com'è e impostando l'opzione multilinea, non funziona. Qual è il problema, cosa devo cambiare? O c'è un modo più semplice per ottenere le parti XML tra questi tag senza regexp?

È stato utile?

Soluzione

credo che l'opzione da usare sia RegexOptions.Singleline invece di RegexOptions.Multiline ( src ). consentire (.) di abbinare le nuove righe dovrebbe funzionare nel tuo caso.

  

... la modalità in cui il punto corrisponde anche alle nuove righe viene chiamata "modalità a riga singola". Questo è un po 'sfortunato, perché è facile confondere questo termine con "modalità multi-linea". La modalità multilinea influenza solo le ancore e la modalità riga singola influisce solo sul punto ... Quando si utilizzano le classi regex del framework .NET, si attiva questa modalità specificando RegexOptions.Singleline, come in Regex.Match (" string " ;, " regex " ;, RegexOptions.Singleline).

Altri suggerimenti

RegExp è uno strumento scadente per xml ... non è possibile caricarlo in un XDocument / XmlDocument e utilizzare xpath? Se chiarisci le modifiche che desideri apportare, mi aspetto che possiamo riempire gli spazi vuoti ... gli spazi dei nomi sono probabilmente la cosa principale per renderlo complesso in questo caso, quindi dobbiamo solo usare un XmlNamespaceManager .

Ecco un esempio che è, per scontato, più complesso di una semplice regex - tuttavia, mi aspetterei che affronti molto meglio le sfumature di xml:

    string xml = @"<foo xmlns:sys=""foobar""><bar/><bar><sys:customtag sys:sid=""1"" sys:type=""Processtart"" />
<sys:tag>value</sys:tag>
here are some other tags
<sys:tag>value</sys:tag>
<sys:customtag sys:sid=""1"" sys:type=""Procesend"" /></bar><bar/></foo>";

    XmlDocument doc = new XmlDocument();
    doc.LoadXml(xml);
    XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable());
    mgr.AddNamespace("sys", "foobar");
    var matches = doc.SelectNodes("//sys:customtag[@sys:type='Processtart']", mgr);
    foreach (XmlElement start in matches)
    {
        XmlElement end = (XmlElement) start.SelectSingleNode("following-sibling::sys:customtag[@sys:type='Procesend'][1]",mgr);
        XmlNode node = start.NextSibling;
        while (node != null && node != end)
        {
            Console.WriteLine(node.OuterXml);

            node = node.NextSibling;
        }
    }

Il carattere regex ". " non corrisponde mai a una nuova riga, anche con l'opzione MultiLine impostata. invece, dovresti usare [\ s \ S] o un'altra combinazione con corrispondenze qualsiasi.

L'opzione MultiLine modifica solo il comportamento di ^ (inizio riga invece di inizio stringa) e $ (fine riga anziché fine stringa)

A proposito: in effetti, regex non è il modo giusto di scansionare un HTML ...

Se hai ancora problemi con questo, potrebbe essere perché stai usando AND con RegexOptions invece di OR.

Questo codice è errato e passerà zero come secondo parametro al costruttore:

Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>",
RegexOptions.Multiline & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant);

Questo codice è corretto (per quanto riguarda l'utilizzo di più flag RegexOptions):

Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>",
RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.CultureInvariant);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top