4 votes

Utilisation d'une expression régulière C# pour remplacer le contenu d'un élément XML

J'écris un code qui gère l'enregistrement de données xml et j'aimerais pouvoir remplacer le contenu de certains éléments (par exemple les mots de passe) dans le document. Je préférerais ne pas sérialiser et analyser le document, car mon code traitera une variété de schémas.

Exemples de documents d'entrée :

doc #1 :

   <user>
       <userid>jsmith</userid>
       <password>myPword</password>
    </user>

doc #2 :

<secinfo>
       <ns:username>jsmith</ns:username>
       <ns:password>myPword</ns:password>
 </secinfo>

Ce que j'aimerais que mon résultat soit :

sortie doc #1 :

<user>
       <userid>jsmith</userid>
       <password>XXXXX</password>
 </user>

Document de sortie n°2 :

<secinfo>
       <ns:username>jsmith</ns:username>
       <ns:password>XXXXX</ns:password>
 </secinfo>

Étant donné que les documents que je vais traiter peuvent avoir une variété de schémas, j'espérais trouver une solution générique d'expression régulière qui pourrait trouver les éléments contenant un mot de passe et masquer le contenu en conséquence.

Puis-je résoudre ce problème en utilisant des expressions régulières et le langage C# ou existe-t-il une méthode plus efficace ?

21voto

Andrew Hare Points 159332

Ce problème est mieux résolu avec XSLT :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="//password">
        <xsl:copy>
            <xsl:text>XXXXX</xsl:text>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Cela fonctionnera pour les deux entrées, à condition que vous gériez correctement les espaces de noms.

Edit : Clarification de ce que j'entends par "gérer correctement les espaces de noms".

Assurez-vous que votre document source qui a le ns Le préfixe du nom a comme espace de nom défini pour le document comme ceci :

<?xml version="1.0" encoding="utf-8"?>
<secinfo xmlns:ns="urn:foo">
    <ns:username>jsmith</ns:username>
    <ns:password>XXXXX</ns:password>
</secinfo>

9voto

Welbog Points 32952

Je dirais qu'il vaut mieux analyser le contenu avec un objet .NET XmlDocument et trouver les éléments de mot de passe en utilisant XPath, puis modifier leurs propriétés innerXML. Cela a l'avantage d'être plus correct (puisque XML n'est pas régulier en premier lieu), et c'est conceptuellement facile à comprendre.

8voto

Michael Kohne Points 8233

D'après mon expérience des systèmes qui tentent d'analyser et/ou de modifier le XML sans analyseur approprié, je peux vous dire que.. : NE LE FAITES PAS . Utilisez un analyseur XML (il y a d'autres réponses ici qui proposent des moyens de le faire rapidement et facilement).

L'utilisation de méthodes non XML pour analyser et/ou modifier un flux XML vous causera TOUJOURS des ennuis à un moment ou à un autre. Je le sais, parce que j'ai ressenti cette douleur.

Je sais qu'il semble que ce serait plus rapide, plus simple à coder, plus facile à comprendre ou autre chose si vous utilisiez la solution regex. Mais vous allez juste rendre la vie de quelqu'un misérable plus tard.

3voto

John Conrad Points 144

Vous peut utiliser des expressions régulières si vous en savez suffisamment sur ce que vous essayez de faire correspondre. Par exemple, si vous recherchez toute balise contenant le mot "password", sans balise intérieure, cette expression régulière fonctionnera :

(<([^>]*?password[^>]*?)>)([^<]*?)(<\/\2>)

Vous pourriez utiliser la même instruction de remplacement C# que dans la réponse de zowat, mais pour la chaîne de remplacement, vous voudriez utiliser "$1XXXXX$4" à la place.

1voto

Kev Points 60744

Regex n'est pas la bonne approche pour cela, j'ai vu que ça se passait très mal quand on s'y attendait le moins.

XDocument est bien plus amusant de toute façon :

XDocument doc = XDocument.Parse(@"
            <user>
                <userid>jsmith</userid>
                <password>password</password>
            </user>");

doc.Element("user").Element("password").Value = "XXXX";

// Temp namespace just for the purposes of the example -
XDocument doc2 = XDocument.Parse(@"
            <secinfo xmlns:ns='http://tempuru.org/users'>
                <ns:userid>jsmith</ns:userid>
                <ns:password>password</ns:password>
            </secinfo>");

doc2.Element("secinfo").Element("{http://tempuru.org/users}password").Value = "XXXXX";

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X