0

I have a XML file which is like this;

<?xml version="1.0" encoding="utf-8"?>
<Data>
  <StringMaps>
    <Menu>
      <String Target="BtnFile" Link="Файл" />
      <String Target="BtnOpen" Link="Открыто" />
      <String Target="BtnSave" Link="Сохранить" />
      <String Target="BtnClose" Link="Закрыть" />
    </Menu>
  </StringMaps>
</Data>

and I load document using XmlDocument.

And then I have two XmlNodeList which are targetAttrs and linkAttrs.

I'm using this code to get the values;

        var targetAttrs = xmldoc1.SelectNodes("/Data/StringMaps/Menu/String/@Target");
        var linkAttrs = xmldoc1.SelectNodes("/Data/StringMaps/Menu/String/@Link");
        foreach (XmlNode temptarget in targetAttrs)
        {
            foreach (XmlNode templink in linkAttrs)
            {
                MessageBox.Show(string.Format("{0} = {1}", temptarget.Value, templink.Value));
            }
        }

I'm trying to get values as key-value pairs like these;

BtnFile = Файл
BtnOpen = Открыто
BtnSave = Сохранить
BtnClose = Закрыть

But I get these;

BtnFile = Файл
BtnFile = Открыто
BtnFile = Сохранить
BtnFile = Закрыть
BtnOpen = Файл
BtnOpen = Открыто
BtnOpen = Сохранить
BtnOpen = Закрыть
BtnSave = Файл
BtnSave = Открыто
BtnSave = Сохранить
BtnSave = Закрыть
BtnClose = Файл
BtnClose = Открыто
BtnClose = Сохранить
BtnClose = Закрыть

If someone writes the code and explains the exact logic, i would be very appreciated.

Knowledge Cube
  • 990
  • 12
  • 35

4 Answers4

2
var strings = xmldoc1.SelectNodes("/Data/StringMaps/Menu/String");
foreach (var node in strings)
{
    MessageBox.Show($"{node.Attributes["Target"].Value} = {node.Attributes["Link"].Value}");
}
Yuriy Faktorovich
  • 67,283
  • 14
  • 105
  • 142
1

The attributes you want belong to the same XMLNode. Your outer loops finds the elements. Then your inner loops looks for the same nodes to display the second attribute.

Search for the Nodes once and display both attributes.

        var MenuItems =xmldoc1.SelectNodes("/Data/StringMaps/Menu/String");

        foreach(XmlNode MenuItem in MenuItems)
        {
             MessageBox.Show(string.Format("{0} ={1}",MenuItem.Attributes["Target"].Value, MenuItem.Attributes["Link"].Value));

        }
user6144226
  • 613
  • 1
  • 8
  • 15
0

I'd recommend an alternative to XmlDocument:use linq XDocument instead and transform it to Dictionary:

var xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<Data>
 <StringMaps>
  <Menu>
   <String Target=""BtnFile"" Link=""Файл"" />
   <String Target=""BtnOpen"" Link=""Открыто"" />
   <String Target=""BtnSave"" Link=""Сохранить"" />
   <String Target=""BtnClose"" Link=""Закрыть"" />
  </Menu>
 </StringMaps>
</Data>";

XDocument xdoc = XDocument.Parse(xml);

var dict = xdoc
    .Descendants("String")
    .ToDictionary(n => n.Attribute("Target").Value, n => n.Attribute("Link").Value);

foreach (var keyValuePair in dict) 
{
    MessageBox.Show($"{keyValuePair.Key} = {keyValuePair.Value}"); 
}
Ofir Winegarten
  • 9,215
  • 2
  • 21
  • 27
  • 1
    First two answers are what i was looking for, but your and jdweng's answer is good alternatives for reading/parsing xml documents. Thanks for your time! – i cant csharp Jun 05 '17 at 16:24
0

Use xml linq :

using System.Collections.ObjectModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;


namespace ConsoleApplication57
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            Dictionary<string,string> dict = doc.Descendants("String")
                .GroupBy(x => (string)x.Attribute("Target"), y => (string)y.Attribute("Link"))
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());
        }


    }

}
jdweng
  • 33,250
  • 2
  • 15
  • 20