2011-06-21 11 views
5

मुझे सी # के साथ एक्सएमएल मानों को पुनः प्राप्त करने में कोई समस्या हो रही है, जो मुझे पता है कि यह सी # और .XML के मेरे सीमित ज्ञान के कारण है।एक्सएमएल फ़ाइल से डेटा पुनर्प्राप्त करना

मैं निम्नलिखित एक्सएमएल फ़ाइल

<PowerBuilderRunTimes> 
    <PowerBuilderRunTime> 
     <Version>12</Version> 
     <Files> 
      <File>EasySoap110.dll</File> 
      <File>exPat110.dll</File> 
      <File>pbacc110.dll</File> 
     </File> 
    </PowerBuilderRunTime> 
</PowerBuilderRunTimes> 

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

var runtimeXml = File.ReadAllText(string.Format("{0}\\{1}", configPath, Resource.PBRuntimes)); 

var doc = XDocument.Parse(runtimeXml); 
var topElement = doc.Element("PowerBuilderRunTimes"); 
var elements = topElement.Elements("PowerBuilderRunTime"); 

foreach (XElement section in elements) 
{ 
    //pbVersion is grabbed earlier. It is the version of PowerBuilder 
    if(section.Element("Version").Value.Equals(string.Format("{0}", pbVersion))) 
    { 
     var files = section.Elements("Files"); 

     var fileList = new List<string>(); 

     foreach (XElement area in files) 
     { 
      fileList.Add(area.Element("File").Value); 
     } 
    } 
} 

मेरे मुद्दा यह है कि स्ट्रिंग सूची ही कभी एक मान के साथ से भर जाता है है, "EasySoap110.dll", और बाकी सब कुछ ध्यान नहीं दिया जाता। क्या कोई मेरी मदद कर सकता है, क्योंकि मुझे नुकसान हुआ है।

+0

कृपया अपना विषय "सी #" से शुरू न करें। यही टैग है। –

उत्तर

10

देखो:

var files = section.Elements("Files"); 

var fileList = new List<string>(); 

foreach (XElement area in files) 
{ 
    fileList.Add(area.Element("File").Value); 
} 

आप प्रत्येक Files तत्व पर पुनरावृत्ति कर रहे हैं, और फिर इसे भीतर पहली File तत्व की खोज। केवल एक Files तत्व है - आपको उसमें File तत्वों पर पुनरावृत्ति करने की आवश्यकता है।

हालांकि, ऐसा करने के निश्चित तरीके हैं। उदाहरण के लिए:

var doc = XDocument.Load(Path.Combine(configPath, Resource.PBRuntimes)); 
var fileList = (from runtime in doc.Root.Elements("PowerBuilderRunTime") 
       where (int) runtime.Element("Version") == pbVersion 
       from file in runtime.Element("Files").Elements("File") 
       select file.Value) 
       .ToList(); 

ध्यान दें कि अगर वहाँ कईPowerBuilderRunTime तत्वों मिलान, कि सभी उन तत्वों की फाइलों सभी साथ एक सूची बना देगा। ऐसा नहीं हो सकता है कि आप क्या चाहते हैं। उदाहरण के लिए, आप चाहते हो सकता है:

var doc = XDocument.Load(Path.Combine(configPath, Resource.PBRuntimes)); 
var runtime = doc.Root 
       .Elements("PowerBuilderRunTime") 
       .Where(r => (int) r.Element("Version") == pbVersion) 
       .Single(); 

var fileList = runtime.Element("Files") 
         .Elements("File") 
         .Select(x => x.Value) 
         .ToList(); 

कि एक मिलान क्रम होता है कि वास्तव में मान्य होगा।

+1

बहुत बढ़िया, यह वही है जो मैं ढूंढ रहा था! मुझे समझने में मदद करने के लिए धन्यवाद! –

-1

आपको इस सामान को एक साधारण XPath क्वेरी के साथ बदलने का प्रयास करना चाहिए। इस बिट पर

 string configPath; 
     System.Xml.XPath.XPathDocument xpd = new System.Xml.XPath.XPathDocument(cofigPath); 
     System.Xml.XPath.XPathNavigator xpn = xpd.CreateNavigator(); 
     System.Xml.XPath.XPathExpression exp = xpn.Compile(@"/PowerBuilderRunTimes/PwerBuilderRunTime/Files//File"); 
     System.Xml.XPath.XPathNodeIterator iterator = xpn.Select(exp); 
     while (iterator.MoveNext()) 
     { 
      System.Xml.XPath.XPathNavigator nav2 = iterator.Current.Clone(); 
      //access value with nav2.value 
     } 
+0

कोई लिंक नहीं और कोई और स्पष्टीकरण नहीं करना मुश्किल हो सकता है। –

2

समस्या यह है कि आपके एक्सएमएल में केवल एक ही तत्व है, जिसमें कई बच्चे हैं। आप फोरच फॉरेप केवल एक ही तत्व के लिए, एक बार निष्पादित करता है, न कि अपने बच्चों के लिए।

var fileSet = files.Elements("File"); 
foreach (var file in fileSet) { 
    fileList.Add(file.Value); 
} 

जो सभी बच्चों तत्वों से अधिक लूप:

कुछ इस तरह करते हैं।

0

मैं हमेशा होमग्राउन एक्सएमएल कॉन्फ़िगरेशन फ़ाइलों को पढ़ने के लिए पाठकों का उपयोग करना पसंद करता हूं। यदि आप इसे मारने पर शायद ही ऐसा कर रहे हैं, लेकिन पाठक तेज़ और सस्ता हैं।

public static class PowerBuilderConfigParser 
{ 
    public static IList<PowerBuilderConfig> ReadConfigFile(String path) 
    { 
     IList<PowerBuilderConfig> configs = new List<PowerBuilderConfig>(); 
     using (FileStream stream = new FileStream(path, FileMode.Open)) 
     { 
      XmlReader reader = XmlReader.Create(stream); 
      reader.ReadToDescendant("PowerBuilderRunTime"); 
      do 
      { 
       PowerBuilderConfig config = new PowerBuilderConfig(); 
       ReadVersionNumber(config, reader); 
       ReadFiles(config, reader); 
       configs.Add(config); 
       reader.ReadToNextSibling("PowerBuilderRunTime"); 
      } while (reader.ReadToNextSibling("PowerBuilderRunTime")); 
     } 
     return configs; 
    } 

    private static void ReadVersionNumber(PowerBuilderConfig config, XmlReader reader) 
    { 

     reader.ReadToDescendant("Version"); 
     string version = reader.ReadString(); 

     Int32 versionNumber; 
     if (Int32.TryParse(version, out versionNumber)) 
     { 
      config.Version = versionNumber; 
     } 
    } 

    private static void ReadFiles(PowerBuilderConfig config, XmlReader reader) 
    { 
     reader.ReadToNextSibling("Files"); 
     reader.ReadToDescendant("File"); 
     do 
     { 
      string file = reader.ReadString(); 
      if (!string.IsNullOrEmpty(file)) 
      { 
       config.AddConfigFile(file); 
      } 
     } while (reader.ReadToNextSibling("File")); 
    } 
} 

public class PowerBuilderConfig 
{ 
    private Int32 _version; 
    private readonly IList<String> _files; 

    public PowerBuilderConfig() 
    { 
     _files = new List<string>(); 
    } 

    public Int32 Version 
    { 
     get { return _version; } 
     set { _version = value; } 
    } 

    public ReadOnlyCollection<String> Files 
    { 
     get { return new ReadOnlyCollection<String>(_files); } 
    } 

    public void AddConfigFile(String fileName) 
    { 
     _files.Add(fileName); 
    } 
} 
+0

ओपी के लिए भी, आपका एक्सएमएल अच्छी तरह से गठित नहीं है, आपकी शुरुआत के साथ समाप्त होती है। –

0

एक और तरीका है एक XmlSerializer उपयोग करने के लिए है।

[Serializable] 
[XmlRoot] 
public class PowerBuilderRunTime 
{ 
[XmlElement] 
public string Version {get;set;} 
[XmlArrayItem("File")] 
public string[] Files {get;set;} 

public static PowerBuilderRunTime[] Load(string fileName) 
{ 
    PowerBuilderRunTime[] runtimes; 
    using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) 
     { 
      var reader = new XmlTextReader(fs); 
      runtimes = (PowerBuilderRunTime[])new XmlSerializer(typeof(PowerBuilderRunTime[])).Deserialize(reader); 
     } 
    return runtimes; 
} 
} 

आप सभी runtimes दृढ़ता से टाइप किया मिलता है, और सभी स्ट्रिंग फ़ाइल नाम लूप करने के लिए प्रत्येक PowerBuilderRunTime के Files संपत्ति का उपयोग कर सकते हैं।

var runtimes = PowerBuilderRunTime.Load(string.Format("{0}\\{1}", configPath, Resource.PBRuntimes)); 
संबंधित मुद्दे