2008-11-14 20 views
12

के साथ नियमित अभिव्यक्ति का सही ढंग से काम नहीं मिल सकता है मेरे पास एक एप्लिकेशन से काफी बड़ा एक्सएमएल आउटपुट है। मुझे इसे अपने प्रोग्राम के साथ संसाधित करने की आवश्यकता है और फिर इसे मूल कार्यक्रम में वापस खिलाएं। इस एक्सएमएल में ऐसे टुकड़े हैं जिन्हें हमारे प्रतिस्थापित करने की आवश्यकता है। दिलचस्प हिस्सा इस तरह दिखता है:मल्टीलाइन

<sys:customtag sys:sid="1" sys:type="Processtart" /> 
    <sys:tag>value</sys:tag> 
    here are some other tags 
    <sys:tag>value</sys.tag> 
<sys:customtag sys:sid="1" sys:type="Procesend" /> 

और दस्तावेज़ में इस तरह के कई टुकड़े हैं।

मुझे इन टैग्स के अंदर सभी एक्सएमएल टुकड़े प्राप्त करने की आवश्यकता है ताकि वे इसमें संशोधन कर सकें। मैं उन टुकड़ों पाने के लिए एक नियमित अभिव्यक्ति लिखा था लेकिन यह काम नहीं करता:

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.Load(@"output.xml"); 
Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>", RegexOptions.Multiline & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant); 
MatchCollection matches = regExp.Matches(xmlDoc.InnerXml); 

मैं एक लाइन में पूरे सामान छोड़ने के लिए और बहु ​​विकल्प के बिना इस regexp कॉल करते हैं, यह हर आवृत्तियां मिल रहा है। फ़ाइल को छोड़कर और मल्टीलाइन विकल्प सेट करके, यह काम नहीं करता है। समस्या क्या है, मुझे क्या बदलना चाहिए? या regexp के बिना इन टैग्स के बीच एक्सएमएल भागों को पाने का कोई आसान तरीका है?

उत्तर

41

मुझे विश्वास है कि RegexOptions.Multiline (src) के बजाय उपयोग करने का विकल्प RegexOptions.Singleline है। (।) न्यूलाइन से मेल खाने की अनुमति आपके मामले में काम करनी चाहिए।

... वह मोड जहां डॉट न्यूलाइन से मेल खाता है उसे "सिंगल-लाइन मोड" कहा जाता है। यह थोड़ा दुर्भाग्यपूर्ण है, क्योंकि इस शब्द को "बहु-रेखा मोड" के साथ मिश्रित करना आसान है। मल्टी-लाइन मोड केवल एंकर को प्रभावित करता है, और सिंगल-लाइन मोड केवल डॉट को प्रभावित करता है ... .NET ढांचे के रेगेक्स वर्गों का उपयोग करते समय, आप RegexOptions.Singleline निर्दिष्ट करके इस मोड को सक्रिय करते हैं, जैसे Regex.Match ("स्ट्रिंग "," regex ", RegexOptions.Singleline)।

+0

यह है कि, धन्यवाद। मेरा मतलब multiline = बहु लाइन मोड भी था। – Biri

4

RegExp xml के लिए एक खराब उपकरण है ... क्या आप इसे XDocument/XmlDocument में लोड नहीं कर सकते हैं और xpath का उपयोग कर सकते हैं? यदि आप उन संशोधनों को स्पष्ट करते हैं जिन्हें आप बनाना चाहते हैं, तो मुझे उम्मीद है कि हम रिक्त स्थान भर सकते हैं ... नामस्थान शायद इस मामले में जटिल बनाने के लिए मुख्य बात हैं, इसलिए हमें केवल XmlNamespaceManager का उपयोग करने की आवश्यकता है।

यहाँ एक उदाहरण है कि, दी, बस एक regex तुलना में अधिक जटिल है - फिर भी, मैं इसे xml की बारीकियों के साथ बेहतर एक बहुत सामना करने के लिए उम्मीद करेंगे:

string xml = @"<foo xmlns:sys=""foobar""><bar/><bar><sys:customtag sys:sid=""1"" sys:type=""Processtart"" /> 
<sys:tag>value</sys:tag> 
here are some other tags 
<sys:tag>value</sys:tag> 
<sys:customtag sys:sid=""1"" sys:type=""Procesend"" /></bar><bar/></foo>"; 

    XmlDocument doc = new XmlDocument(); 
    doc.LoadXml(xml); 
    XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable()); 
    mgr.AddNamespace("sys", "foobar"); 
    var matches = doc.SelectNodes("//sys:customtag[@sys:type='Processtart']", mgr); 
    foreach (XmlElement start in matches) 
    { 
     XmlElement end = (XmlElement) start.SelectSingleNode("following-sibling::sys:customtag[@sys:type='Procesend'][1]",mgr); 
     XmlNode node = start.NextSibling; 
     while (node != null && node != end) 
     { 
      Console.WriteLine(node.OuterXml); 

      node = node.NextSibling; 
     } 
    } 
+0

मैंने XPath विकल्पों को देखा है लेकिन मुझे कुछ भी नहीं मिला है जो मुझे टैग्स के बीच एक्सएमएल सामग्री वापस दे सकता है, जो एक्सएमएल-वार से संबंधित नहीं हैं (मेरा मतलब है कि वे बिंदु से एक दूसरे के प्रारंभ-बंद टैग नहीं हैं एक्सएमएल का)। शायद आपके पास कोई विचार है? – Biri

+0

खैर, xml का उद्देश्य पेड़ के रूप में उपयोग किया जाना है ... एक साधारण विकल्प केवल ... का उपयोग करना होगा - लेकिन मुझे एक त्वरित रूप दिखाई देगी। .. –

+0

हां, मैं इसे संभाल सकता हूं, लेकिन दुर्भाग्यवश एक्सएमएल एक ऐसे एप्लिकेशन से आ रहा है जिसे मैं नहीं बदल सकता, और मुझे इसे इस प्रारूप में उसी एप्लिकेशन पर वापस देना होगा। मैं अंदर एक्सएमएल टैग नहीं बदल सकता। – Biri

4

regex चार "।" MultiLine विकल्प के साथ भी एक नई लाइन से मेल नहीं खाता है। इसके बजाय, आपको [\s\S] या मैचों के साथ अन्य संयोजन का उपयोग करना चाहिए।

MultiLine विकल्प केवल के व्यवहार को संशोधित करता है^(शुरू के- लाइन के बजाय के लिए शुरू के- स्ट्रिंग) और $ (अंत लाइन के अंत स्ट्रिंग के बजाय)

Btw: दरअसल , regex HTML को स्कैन करने का सही तरीका नहीं है ...

4

यदि आपको अभी भी समस्याएं आ रही हैं, तो ऐसा इसलिए हो सकता है क्योंकि आप OR के बजाय अपने RegexOptions का उपयोग कर रहे हैं।

इस कोड गलत है और शून्य निर्माता के लिए दूसरा पैरामीटर के रूप में पारित करेंगे:

Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>", 
RegexOptions.Multiline & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant); 

इस कोड सही है (जहां तक ​​कई RegexOptions झंडे का उपयोग कर के रूप में):

Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>", 
RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.CultureInvariant); 
संबंधित मुद्दे