我怎样才能使正则表达式工作?

时间:2012-02-01 16:02:40

标签: c# regex

我想使用正则表达式来查找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); 

我无法弄清楚如何遍历elementsWithPossibleCCNumbers中的每个属性,例如:

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位的第二个元素,它只会替换部分属性值。

4 个答案:

答案 0 :(得分:3)

我写了另一种尝试的方法。正则表达式现在只验证属性值而不是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);
    }
}

答案 1 :(得分:3)

由于您的XML可能有很大差异,我会做类似以下的事情。

假设XML如:

<Details> 
<CreditCard cardnum="1234567890123456" 
            ccv="123" 
            exp="0212" 
            cardType="1" 
            name="joe" /> 
</Details> 

不可知代码:

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元素名称。我倾向于使用正则表达式作为最后的手段,特别是如果有更好的东西可以解析我的所有数据。

更新1

elementsWithPossibleCCNumbers是XML元素,包含 1或MORE 属性,长度为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());

答案 2 :(得分:2)

尝试使用:     百分比抑制率^&GT;] + [0-9] {16} [^&GT;] +&GT;

编辑:这可能更有效 - &lt;([^ 0-9] +)([0-9] {16})([^>] +)&gt;

答案 3 :(得分:1)

不要使用Regex来解析XML。它并不适合它。

如何使用XmlDocument或XDocument?