如何使正则表达式工作
本文关键字:工作 正则表达式 何使 | 更新日期: 2023-09-27 18:22:04
我想用正则表达式找到16位数字的父节点并返回整个部分,但不知道如何返回,所以给定:
<Details>
<CreditCard cardnum="1234567890123456" ccv="123" exp="0212" cardType="1" name="joe" />
</Details>
我想退货:
<CreditCard cardnum="1234567890123456" ccv="123" exp="0212" cardType="1" name="joe" />
然后,我将使用解析xml,获取每个数字属性并将其删除
我尝试过.*('d{13,16}).*
,但它可以获得每个字符。
我做过一次:
XElement element = XElement.Parse(xml); // XDocument.Load(xmlFile).Root
IEnumerable<XElement> elementsWithPossibleCCNumbers =
element.Descendants()
.Where(d => d.Attributes()
.Where(a => a.Value.Length == 16)
.Count() == 1);
我不知道如何循环元素WithPossibleCCNumbers中的每个属性,例如:
foreach(var x in elementsWithPossibleCCNumbers)
{
//If attribute is number, replace value with empty string
}
注意:我暂时删除了int.TryParse。
我决定这样做:
IEnumerable<XElement> elementsWithPossibleCCNumbers =
element.Descendants()
.Where(d => d.Attributes()
.Where(a => a.Value.Length >= 13 && a.Value.Length <= 16)
.Count() == 1).Select(x=>x);
foreach(var x in elementsWithPossibleCCNumbers)
{
foreach(var a in x.Attributes())
{
xml = xml.Replace(a.Value, new String('*',12));
}
}
但是,如果我有一个属性为16位的第二个元素,它只会替换属性值的一部分。
由于您的XML可能会有很大的变化,我会做如下操作。
假设类似XML:
<Details>
<CreditCard cardnum="1234567890123456"
ccv="123"
exp="0212"
cardType="1"
name="joe" />
</Details>
不可知的ish代码:
XElement element = XElement.Parse(xml); // XDocument.Load(xmlFile).Root
int ccNumber;
IEnumerable<XElement> elementsWithPossibleCCNumbers =
element.Descendants()
.Where(d => d.Attributes()
.Where(a => a.Value.Length == 16)
.Where(a => int.TryParse(a.Value, out ccNumber))
.FirstOrDefault() != null);
// Do not use ccNumber
// Use elementsWithPossibleCCNumbers
这可以扩展到包括许多属性。。。
IEnumerable<XElement> elementsWithPossibleCCNumbers =
element.Descendants()
.Where(d => d.Attributes()
.Where(a => a.Value.Length == 16)
.Where(a => int.TryParse(a.Value, out ccNumber))
.FirstOrDefault() != null
&& d.Attributes().Count() == 5);
有许多可能性不包括使用Regex,也不包括对XML元素名称进行硬编码。我倾向于使用Regex作为最后的手段,尤其是如果有更好的东西可以为我解析所有数据
更新1
elementsWithPossibleCCNumbers
是包含1或MORE属性的XML元素,这些属性的长度为16位,是一个整数。既然如此,你不能说,所以我会把它改成…
IEnumerable<XElement> elementsWithPossibleCCNumbers =
element.Descendants()
.Where(d => d.Attributes()
.Where(a => a.Value.Length == 16)
.Where(a => int.TryParse(a.Value, out ccNumber))
.Count() == 1);
// Where only 1 attribute is 16 length and an int
再次扩展。。。
IEnumerable<XAttribute> attributesWithPossibleCCNumbers =
element.Descendants()
.Where(d => d.Attributes()
.Where(a => a.Value.Length == 16)
.Where(a => int.TryParse(a.Value, out ccNumber))
.Count() == 1)
.Select(e => e.Attributes()
.Where(a => a.Value.Length == 16)
.Where(a => int.TryParse(a.Value, out ccNumber))
.First());
我写了另一个方法来尝试。regex现在只验证属性值,而不验证XML本身。我不知道你想从这个方法中得到什么,但这至少会让你开始不使用Regex for XML。
[Test]
public void X()
{
const string xml = "<Details><CreditCard cardnum='"1234567890123456'" ccv='"123'" exp='"0212'" cardType='"1'" name='"joe'" /><donotfind>333</donotfind></Details>";
var doc = new XmlDocument();
doc.LoadXml(xml);
Console.WriteLine(doc.Name);;
foreach(XmlNode x in doc.ChildNodes)
{
ExploreNode(x);
}
}
void ExploreNode(XmlNode node)
{
Console.WriteLine(node.Name);
if (node.Attributes != null)
{
foreach (XmlAttribute attr in node.Attributes)
{
Console.WriteLine("'t{0} -> {1}", attr.Name, attr.Value);
if (attr.Value.Length == 16 && Regex.IsMatch(attr.Value, @"'d{16}"))
{
Console.WriteLine("'t'tCredit Card # found!");
}
}
}
foreach (XmlNode child in node.ChildNodes)
{
ExploreNode(child);
}
}
尝试使用:<[^>]+[0-9]{16}[^>][>>
编辑:这可能更有效-<([^>0-9]+)([0-9]{16})([^>]+)>
不要使用Regex来解析XML。它不太适合。
不如改用XmlDocument或XDocument?