2010-11-30 4 views
1

Je sais que l'utilisation d'expressions régulières pour analyser ou manipuler HTML/XML est une mauvaise idée et je ne le ferais jamais. Mais compte tenu du manque d'alternatives.Remplacer le texte non contenu dans un tag en utilisant Regex ou XmlParser

J'ai besoin de remplacer le texte à l'intérieur d'une chaîne qui ne fait pas déjà partie d'une étiquette (idéalement une étiquette d'étendue avec un ID spécifique) en utilisant C#.

Par exemple, disons que je veux remplacer tous les instaces de ABC dans le texte suivant, qui ne sont pas dans une période avec le texte alternatif (une autre span dans mon cas)

ABC at start of line or ABC here must be replaced but, <span id="__publishingReusableFragment" >ABC inside span must not be replaced with anything. Another ABC here </span> this ABC must also be replaced

J'ai essayé d'utiliser regex avec les deux regardent devant et regardent derrière l'assertion. Diverses combinaisons le long des lignes de

string regexPattern = "(?<!id=\"__publishingReusableFragment\").*?" + stringToMatch + ".*?(?!span)"; 

mais ont abandonné là-dessus.

J'ai essayé de le charger dans un XElement et d'essayer de créer un script à partir de là et d'obtenir du texte à l'intérieur d'un nœud. Mais ne pouvait pas comprendre cela non plus.

XElement xel = XElement.Parse("<payload>" + inputString + @"</payload>"); 
XmlWriter requiredWriter = xel.CreateWriter(); 

J'espère en quelque sorte d'utiliser l'écrivain pour obtenir les chaînes qui ne font pas partie d'un nœud et de les remplacer. Fondamentalement, je suis ouvert à toutes les suggestions/solutions pour résoudre ce problème.

Merci d'avance pour l'aide.

Répondre

1
resultString = Regex.Replace(subjectString, 
    @"(?<!    # assert that we can't match the following 
         # before the current position: 
         # An opening span tag with specified id 
    <\s*span\s*id=""__publishingReusableFragment""\s*> 
    (?:    # if it is not followed by... 
     (?!<\s*/\s*span) # a closing span tag 
     .     # at any position between the opening tag 
    )*     # and our text 
    )     # End of lookbehind assertion 
    ABC     # Match ABC", 
    "XYZ", RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); 

travaillera avec toutes les mises en garde au sujet de l'analyse syntaxique HTML (que vous semblez savoir, donc je ne vais pas les répéter ici) encore valide.

L'expression régulière correspond à ABC si elle n'est pas précédée d'une balise d'ouverture <span id=__publishingReusableFragment"> et s'il n'y a pas de balise de fermeture <span> entre les deux. Il échouera évidemment s'il peut y avoir des balises <span> imbriquées.

+0

Ça a l'air bien. Mais qu'en est-il s'il y avait des attributs supplémentaires dans la balise span, par exemple: ... ... J'ai essayé de remplacer la partie span de la regex suit <\ s * span. *? id = "" __ publishingReusableFragment "". *?> Mais maintenant, il ne correspond pas après la fin de la balise span - ... this ABC ... – Chaitanya

+0

Vous commencez à courir dans toutes les raisons pour lesquelles l'analyse HTML avec regex n'est pas une bonne idée. Si vos attributs ne contiennent jamais un '>', vous pouvez utiliser '<\s*span[^>] * id =" "__ publishingReusableFragment" "[^>] *>' et espérer le meilleur. –

+0

Ouais, c'était tout, merci. Ouais, c'est pourquoi j'espérais que marcher avec LinqToXML ou une bonne librairie LinqToHtml pourrait être une idée. Il ne s'agit que d'un outil d'importation unique, qui doit fournir des données pour réduire le post-traitement manuel. – Chaitanya

1

Je sais que peu laid, mais cela ne fonctionnera

var s = 
    @"ABC at start of line or ABC here must be replaced but, <span id=""__publishingReusableFragment"" >ABC inside span must not be replaced with anything. Another ABC here </span> this ABC must also be replaced"; 
var newS = string.Join("</span>",s.Split(new[] {"</span>"}, StringSplitOptions.None) 
    .Select(t => 
     { 
      var bits = t.Split(new[] {"<span"}, StringSplitOptions.None); 
      bits[0] = bits[0].Replace("ABC","DEF"); 
      return string.Join("<span", bits); 
     })); 
+0

Pas moche du tout. C'est une excellente façon de faire ce qui doit être fait (ce qui est un peu moche). Le seul problème est qu'il ignore toutes les envergures. pas seulement des travées avec un identifiant particulier, comme l'expression rationnelle. Cela aurait probablement pu être élargi pour me convenir et aiderait dans beaucoup d'autres situations. – Chaitanya

Questions connexes