Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C#正则表达式替换XML元素内容_C#_.net_Xml_Regex_Parsing - Fatal编程技术网

使用C#正则表达式替换XML元素内容

使用C#正则表达式替换XML元素内容,c#,.net,xml,regex,parsing,C#,.net,Xml,Regex,Parsing,我正在编写一些处理记录xml数据的代码,我希望能够替换文档中某些元素(例如密码)的内容。我不希望序列化和解析文档,因为我的代码将处理各种模式 输入文档示例: //input is a String with some valid XML XmlDocument doc = new XmlDocument(); doc.LoadXml(input); XmlNodeList nodeList = doc

我正在编写一些处理记录xml数据的代码,我希望能够替换文档中某些元素(例如密码)的内容。我不希望序列化和解析文档,因为我的代码将处理各种模式

输入文档示例:

            //input is a String with some valid XML
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(input);
            XmlNodeList nodeList = doc.SelectNodes("//*");

            foreach (XmlNode node in nodeList)
            {
                if (node.Name.ToUpper().Contains("PASSWORD"))
                {
                    node.InnerText = "XXXX";
                }
                else if (node.Attributes.Count > 0)
                {
                    foreach (XmlAttribute a in node.Attributes)
                    {
                        if (a.LocalName.ToUpper().Contains("PASSWORD"))
                        {
                            a.InnerText = "XXXXX";
                        }
                    }
                }    
            }
文件#1:


名缩写和姓
迈普沃德
文件2:


名缩写和姓
迈普沃德
我希望我的输出是:

输出文件#1:


名缩写和姓
XXXXX
输出文件#2:


名缩写和姓
XXXXX
因为我将要处理的文档可能有多种模式,所以我希望能够找到一个很好的通用正则表达式解决方案,它可以找到其中包含密码的元素,并相应地屏蔽内容


我可以用正则表达式和C#来解决这个问题吗?或者有更有效的方法吗?

我认为最好使用.NET XmlDocument对象解析内容,使用XPath查找密码元素,然后更改它们的innerXML属性。它的优点是更加正确(因为XML一开始不是规则的),而且概念上也很容易理解。

这个问题最好用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>

如果您对要匹配的内容了解得足够多,则可以使用正则表达式。例如,如果要查找任何包含单词“password”且没有内部标记的标记,则此正则表达式将起作用:

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

(]*?password[^>]*?)>([^根据在没有合适的解析器的情况下尝试解析和/或修改XML的系统的经验,让我说:不要这样做。。使用XML解析器(这里有其他方法可以快速轻松地做到这一点)

使用非xml方法来解析和/或修改xml流在将来的某个时候总是会让你感到痛苦


我知道,如果你使用正则表达式解决方案,似乎在运行时会更快/更容易编写代码/更容易理解/无论发生什么。但你以后只会让某人的生活更悲惨。

正则表达式是一种错误的方法,我看到它在你最意想不到的时候出错了

XDocument无论如何要有趣得多:

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";
XDocument doc=XDocument.Parse(@)
名缩写和姓
密码
");
doc.Element(“用户”).Element(“密码”).Value=“XXXX”;
//临时名称空间仅用于示例目的-
XDocument doc2=XDocument.Parse(@)
名缩写和姓
密码
");
doc2.元素(“secinfo”).元素(“{http://tempuru.org/users}密码“).Value=“XXXXX”;

以下是我在使用XMLDocument时想到的,它可能没有XSLT那么灵巧,但应该足够通用,可以处理各种文档:

            //input is a String with some valid XML
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(input);
            XmlNodeList nodeList = doc.SelectNodes("//*");

            foreach (XmlNode node in nodeList)
            {
                if (node.Name.ToUpper().Contains("PASSWORD"))
                {
                    node.InnerText = "XXXX";
                }
                else if (node.Attributes.Count > 0)
                {
                    foreach (XmlAttribute a in node.Attributes)
                    {
                        if (a.LocalName.ToUpper().Contains("PASSWORD"))
                        {
                            a.InnerText = "XXXXX";
                        }
                    }
                }    
            }

XSLT存在的主要原因是能够转换XML结构,这意味着XSLT是一种样式表,可以用来改变元素的顺序或改变元素的内容。因此,这是一种典型的情况,强烈建议使用XSLT,而不是像Andrew Hare在前一篇文章中所说的那样使用解析

我当然会避免使用正则表达式,因为还有很多其他优秀的工具可以做您想做的事情。即使正则表达式能够做到这一点(它们没有),但有多种模式使得使用某种形式的解析器变得更为必要。您的观点很好,我认为这里提出的其他一些解决方案(XSLT、XPATH或XDocument)这将使我在未来免于一些痛苦。很少有绝对规则不存在异常。“永远不要使用字符串操作工具来解析或修改XML”是其中之一。我认为您希望对元素和属性都使用LocalName。此外,如果您将此作为遍历XML树的递归函数,则不必首先构建文档中所有元素的列表。不,您不能(或不应该)因为正则表达式不知道层次结构,无法加载和解析命名或数字实体,更不用说外部doctype了,CDATA有问题,无法处理名称空间。改用XSLT。这样做只会打开一罐蠕虫。问题是显式提到正则表达式。为什么每个人都试图提供不可行的解决方案相反
<?xml version="1.0" encoding="utf-8"?>
<secinfo xmlns:ns="urn:foo">
    <ns:username>jsmith</ns:username>
    <ns:password>XXXXX</ns:password>
</secinfo>
(<([^>]*?password[^>]*?)>)([^<]*?)(<\/\2>)
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";
            //input is a String with some valid XML
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(input);
            XmlNodeList nodeList = doc.SelectNodes("//*");

            foreach (XmlNode node in nodeList)
            {
                if (node.Name.ToUpper().Contains("PASSWORD"))
                {
                    node.InnerText = "XXXX";
                }
                else if (node.Attributes.Count > 0)
                {
                    foreach (XmlAttribute a in node.Attributes)
                    {
                        if (a.LocalName.ToUpper().Contains("PASSWORD"))
                        {
                            a.InnerText = "XXXXX";
                        }
                    }
                }    
            }