2010-05-12 3 views
0

J'ai un fichier xml avec le contenu du fichier xml simplifiée suivante:.Net, XML et Regex - Comment faire correspondre un élément de collection spécifique?

<CollectionItems> 
    <CollectionItem> 
     <Element1>Value1</Element1> 
     <Element2> 
      <SubElement1>SubValue1</SubElement1> 
      <SubElement2>SubValue2</SubElement2> 
      <SubElement3>SubValue3</SubElement3> 
     </Element2> 
     <Element3>Value3</Element3> 
    </CollectionItem> 
    <CollectionItem> 
     <Element1>Value1</Element1> 
     <Element2> 
      <SubElement1>SubValue1</SubElement1> 
      <SubElement2 /> 
      <SubElement3>SubValue3</SubElement3> 
     </Element2> 
     <Element3>Value3</Element3> 
    </CollectionItem> 
    <CollectionItem> 
     <Element1>Value1</Element1> 
     <Element2> 
      <SubElement1>SubValue1</SubElement1> 
      <SubElement2>SubValue2</SubElement2> 
      <SubElement3>SubValue3</SubElement3> 
     </Element2> 
     <Element3>Value3</Element3> 
    </CollectionItem> 
</CollectionItems> 

Je cherche à écrire un regex en .Net qui correspond à tout collectionItem où SubElement2 est vide (au milieu collectionItem dans cet exemple).

I ont l'expression rationnelle suivant la mesure (mode SingleLine activé):

<CollectionItem>.+?<SubElement2 />.+?</CollectionItem> 

Le problème est qu'il est correspondant à l'ouverture de la première collectionItem par la fin de la deuxième collectionItem. Je comprends pourquoi c'est le cas, mais je ne sais pas comment modifier l'expression rationnelle pour qu'elle corresponde uniquement au centre CollectionItem.

Edit: Quant à savoir pourquoi regex par opposition à quelque chose d'autre:

  1. je tentais de modifier le fichier dans un éditeur de texte pour la simplicité.
  2. Après que je ne pouvais pas comprendre comment le faire dans regex, je voulais savoir si cela pourrait se faire (et comment) dans l'intérêt de l'apprentissage.

Merci!

+0

votre xml est mauvais dans l'exemple. SubElement2 et SubElement3 ont toutes deux des balises fermantes SubElement1 – Greg

+0

Oups, vous avez raison. C'est corrigé maintenant. –

Répondre

2

Vous pouvez utiliser

<CollectionItem>((?!<CollectionItem>).)+?<SubElement2 />.+?</CollectionItem> 

Cela garantit qu'aucun <CollectionItem> plus vient entre la balise de début et la balise <SubElement2 />.

+0

Cela fonctionne! Je vous remercie. –

5

Pourquoi essayez-vous d'utiliser une expression régulière? Vous avez un très bon modèle de domaine (XML) - pourquoi ne pas chercher à la place? Ainsi, par exemple dans LINQ to XML:

var collectionsWithEmptySubElement2 = 
     document.Descendants("SubElement2") 
       .Where(x => x.IsEmpty) 
       .Select(x => x.Ancestors("CollectionItem").FirstOrDefault()); 

ou

var collectionsWithEmptySubElement2 = 
     document.Descendants("CollectionItem") 
       .Where(x => x.Descendants("SubElement2").Any(sub => sub.IsEmpty)); 
+0

Je l'avais envisagé d'utiliser LINQPad pour ce faire (je suis en train de corriger un fichier de données XML avec des valeurs non valides), mais je viens est devenu curieux de savoir comment vous réellement faire dans RegEx si vous vouliez. –

3

Ceci est XML - pourquoi essayez-vous de faire avec Regex? XPath n'aurait-il pas plus de sens?

+0

'/ CollectionItems/CollectionItem [./*/ SubElement2 = '']' – Greg

Questions connexes