我正在编写一些处理日志记录xml数据的代码,我希望能够替换文档中某些元素(例如密码)的内容。我宁愿不序列化和解析文档,因为我的代码将处理各种模式。
示例输入文档:
doc#1:
<user>
<userid>jsmith</userid>
<password>myPword</password>
</user>
doc#2:
<secinfo>
<ns:username>jsmith</ns:username>
<ns:password>myPword</ns:password>
</secinfo>
我希望我的输出是:
输出文档#1:
<user>
<userid>jsmith</userid>
<password>XXXXX</password>
</user>
输出文档#2:
<secinfo>
<ns:username>jsmith</ns:username>
<ns:password>XXXXX</ns:password>
</secinfo>
由于我将要处理的文档可能有各种模式,我希望能找到一个很好的通用正则表达式解决方案,它可以找到包含密码的元素并相应地屏蔽内容。
我可以使用正则表达式和C#来解决这个问题,还是有更有效的方法?
答案 0 :(得分:21)
使用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>
只要正确处理命名空间,这将适用于两个输入。
确保具有ns
名称前缀的源文档具有为文档定义的命名空间,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<secinfo xmlns:ns="urn:foo">
<ns:username>jsmith</ns:username>
<ns:password>XXXXX</ns:password>
</secinfo>
答案 1 :(得分:8)
我说你最好用.NET XmlDocument对象解析内容并使用XPath查找密码元素,然后更改它们的innerXML属性。它具有更正确的优点(因为XML首先不是常规的),并且它在概念上很容易理解。
答案 2 :(得分:8)
根据使用没有适当解析器来尝试解析和/或修改XML的系统的经验,让我说:不要做它。使用XML解析器(此处还有其他答案可以快速轻松地完成此操作)。
使用非xml方法来解析和/或修改XML流将总是会让您在将来的某个时刻感到痛苦。我知道,因为我感到痛苦。
我知道如果您使用正则表达式解决方案,它似乎会更快 - 运行时/更简单 - 代码/更容易理解/无论如何。但是你以后只会让别人的生活变得悲惨。
答案 3 :(得分:1)
如果您对自己想要匹配的内容有足够的了解,可以使用正则表达式。例如,如果您正在查找其中没有内部标记的任何标记“密码”,则此正则表达式将起作用:
(<([^>]*?password[^>]*?)>)([^<]*?)(<\/\2>)
您也可以在zowat的答案中使用相同的C#替换语句,但对于替换字符串,您可能希望使用“$ 1XXXXX $ 4”。
答案 4 :(得分:1)
正则表达式对此是错误的方法,我看到它在你最不期望它时会出现如此严重的错误。
无论如何,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";
答案 5 :(得分:1)
这是我在使用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";
}
}
}
}
答案 6 :(得分:1)
XSLT存在的主要原因是能够转换XML结构,这意味着XSLT是一种样式表,可用于改变元素的顺序和更改元素的内容。因此,这是一个典型的情况,强烈建议使用XSLT而不是解析,就像Andrew Hare在之前的帖子中所说的那样。