簡體   English   中英

我怎樣才能使正則表達式起作用?

[英]How can I get the regex to work?

我想使用正則表達式來查找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位數字,則它僅替換部分屬性值。

我寫了另一種方法來嘗試。 現在,正則表達式僅驗證屬性值,而不驗證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);
    }
}

由於您的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元素名稱進行硬編碼。 我傾向於將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());

嘗試使用:<[^>] + [0-9] {16} [^>] +>

編輯:這可能更有效-<([^> 0-9] +)([0-9] {16})([^>] +)>

不要使用Regex解析XML。 它不太適合它。

如何改用XmlDocument或XDocument?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM