๋ฐ˜์‘ํ˜•

XML์ด๋ž€?

XML์€ eXtensible Markup Language์•ฝ์ž๋กœ, ๋ง ๊ทธ๋Œ€๋กœ 'ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ๋งˆํฌ์—… ์–ธ์–ด'๋ฅผ ๋œปํ•˜๋Š”๋ฐ, ์ข€ ๋” ์˜๋ฏธ๋ฅผ ํ’€์ž๋ฉด '๋ฐ์ดํ„ฐ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ทœ์น™์„ ์ œ๊ณตํ•˜๋Š” ๋งˆํฌ์—… ์–ธ์–ด'์ž…๋‹ˆ๋‹ค.

XML์„ ๋ชฐ๋ž์„ ๋•Œ์—๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ์„ค์ • ํŒŒ์ผ๋กœ INI ํฌ๋งท์„ ์‚ฌ์šฉํ–ˆ์—ˆ์œผ๋‚˜, XML์„ ์ ‘ํ•œ ์ดํ›„๋กœ๋Š” ์ค„๊ณง XML ํŒŒ์ผ๋งŒ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ๋‚˜์—ด์ด ๊ฐ€๋Šฅํ•˜๊ณ , ๋ฐ์ดํ„ฐ์˜ ๊นŠ์ด๋„ ์ž์œ ๋กญ๊ฒŒ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ, ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ ์€ ์ง๋ ฌํ™”(Serialization)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด์™€ ์—ฐ๋™์ด ์‰ฌ์›Œ ์ฝ๊ณ  ์“ฐ๊ธฐ๊ฐ€ ์•„์ฃผ ํŽธ๋ฆฌํ•˜๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ, ๋ณธ๋ฌธ์—์„œ๋Š” XML ํŒŒ์ผ์˜ ๊ตฌ์กฐ์™€ C#์œผ๋กœ ์–ด๋–ป๊ฒŒ ์ฝ๊ณ  ์“ฐ๋Š”์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ , Serialization์„ ์‚ฌ์šฉํ•ด ์–ด๋–ป๊ฒŒ ๊ฐ์ฒดํ™”ํ•˜๋Š”์ง€ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

XML ๊ตฌ์กฐ

XML์€ ํŠธ๋ฆฌ(Tree) ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ๋…ธ๋“œ(Node)๋ฅผ ์š”์†Œ(Element)๋ผ๊ณ  ๋ถ€๋ฅด๊ณ , ๋ฃจํŠธ(Root)๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ํ•˜์œ„์š”์†Œ๊ฐ€ ์ด์–ด์ง‘๋‹ˆ๋‹ค. ํ•˜์œ„ ์š”์†Œ ์ž…์žฅ์—์„œ ์ƒ์œ„ ์š”์†Œ๋ฅผ ๋ถ€๋ชจ(Parent) ์š”์†Œ๋ผ๊ณ  ๋ถ€๋ฅด๊ณ , ๋ฐ˜๋Œ€๋กœ๋Š” ์ž์‹(Child) ์š”์†Œ๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

XML ํŠธ๋ฆฌ ๊ตฌ์กฐ

๊ทธ๋ฆฌ๊ณ  ๊ฐ ์š”์†Œ๋Š” ์†์„ฑ(Attribute)์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์ด๋ฏธ์ง€๋Š” Product ๋…ธ๋“œ ์ด๋ฆ„์— 'index'๋ผ๋Š” ์†์„ฑ๊ณผ '0'์ด๋ผ๋Š” ๊ฐ’์ด ํฌํ•จ๋œ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค.

๋…ธ๋“œ์— ์†์„ฑ์ด ํฌํ•จ๋œ ๋ชจ์Šต

๊ทธ๋Ÿผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฐ˜ ๋ณ„๋กœ ํ•™์ƒ๋“ค์˜ ๊ฐœ์ธ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด XML์„ ์˜ˆ์‹œ๋กœ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. A์™€ B๋ผ๋Š” ์ด๋ฆ„์˜ Class๊ฐ€ ์žˆ๊ณ , Class ๋ณ„๋กœ ๋ช‡ ๋ช…์˜ ํ•™์ƒ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ ํ•™์ƒ์˜ ์ •๋ณด์—๋Š” ์ด๋ฆ„๊ณผ ํ•ธ๋“œํฐ ๋ฒˆํ˜ธ๊ฐ€ ๋‹ด๊ฒจ ์žˆ์Šต๋‹ˆ๋‹ค.

<?xml version="1.0"?>
<Root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Class Name="A">
	<Student Index="0">
	  <Name>์ฒ ์ˆ˜</Name>
	  <Phone>010-xxxx-xxxx</Phone>
	</Student>  
	<Student Index="1">
	  <Name>์˜ํฌ</Name>
	  <Phone>010-yyyy-yyyy</Phone>
	</Student>  
  </Class>
  <Class Name="B">
	<Student Index="0">
	  <Name>์งฑ๊ตฌ</Name>
	  <Phone>010-zzzz-zzzz</Phone>
	</Student>  
	<Student Index="1">
	  <Name>๋งน๊ตฌ</Name>
	  <Phone>010-xxxx-yyyy</Phone>
	</Student>  
	<Student Index="2">
	  <Name>๊ธฐ์˜</Name>
	  <Phone>010-xxxx-zzzz</Phone>
	</Student>  
  </Class>
</Root>

์‚ฌ์‹ค ๊ตณ์ด 'Index' ์†์„ฑ์„ ๋ถ™์ผ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Name๊ณผ Phone ๋…ธ๋“œ๋„ ์†์„ฑ์œผ๋กœ ๋„ฃ์œผ๋ฉด ๋”์šฑ ์‹ฌํ”Œํ•ด์ง€์ฃ . ๊ทธ๋Ÿผ ์œ„ ํŒŒ์ผ์„ ์ฝ”๋“œ๋กœ ์–ด๋–ป๊ฒŒ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋Š”์ง€, ์–ด๋–ป๊ฒŒ ๋…ธ๋“œ์˜ ๊ฐ’์— ์ ‘๊ทผํ•˜๋Š”์ง€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

using System.Xml;
 
private void btnOpen_Click(object sender, EventArgs e)
{
    try
    {
        OpenFileDialog dlg = new OpenFileDialog();
        if (dlg.ShowDialog() == DialogResult.OK )
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(dlg.FileName);
 
            XmlNodeList nodes = doc.SelectNodes(@"/Root/Class");
            var classes = nodes.Count; //๋ฐ˜ํ™˜ ๊ฐ’: 2
            
            nodes = doc.SelectNodes(@"/Root/Class[@Name='B']/Student");
            var students = nodes.Count; //๋ฐ˜ํ™˜ ๊ฐ’: 3
 
            var node = doc.SelectSingleNode(@"/Root/Class[@Name='B']/Student[@Index='1']/Name");
            var name = node.InnerText; //๋ฐ˜ํ™˜ ๊ฐ’: ๋งน๊ตฌ
        }
    }
    catch(Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}

๋…ธ๋“œ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์˜ฌ๋ฐ”๋ฅธ XPath(XML Path) ์‹์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์œ„ ์˜ˆ์‹œ์ฒ˜๋Ÿผ, ์ ˆ๋Œ€ ๊ฒฝ๋กœ ๋˜๋Š” ์ƒ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ์ž…๋ ฅํ•ด์•ผ ํ•˜๋ฉฐ, ์†์„ฑ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋…ธ๋“œ์— [@์†์„ฑ='๊ฐ’'] ํ‚ค์›Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ, ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋…ธ๋“œ ์‚ฝ์ž…, ์‚ญ์ œ, ๊ฐ’ ๋ณ€๊ฒฝ ๋“ฑ์˜ ํŽธ์ง‘๋„ ์›ํ•œ๋‹ค๋ฉด CreateElement, RemoveChild, AppendChild, CreateAttribute ๋“ฑ์˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

XMLDocument์˜ ์ž์„ธํ•œ ์‚ฌ์šฉ๋ฒ•์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

https://learn.microsoft.com/ko-kr/dotnet/api/system.xml.xmldocument?view=netframework-4.8

 

XmlDocument ํด๋ž˜์Šค (System.Xml)

XML ๋ฌธ์„œ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์„œ์—์„œ XML ๋กœ๋“œ, ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ, ํŽธ์ง‘, ์ถ”๊ฐ€ ๋ฐ ์œ„์น˜ ์ง€์ •์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

learn.microsoft.com

ํ”„๋กœ๊ทธ๋žจ ์šด์˜ ์ค‘ XML์„ ํŽธ์ง‘ํ•˜๊ธธ ์›ํ•œ๋‹ค๋ฉด ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ฒŒ Wrapper Class๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

XML ์ง๋ ฌํ™”

์ง๋ ฌํ™”(Serialize)๋ž€, ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ์ด๋‚˜ ์ „์†ก์„ ์œ„ํ•ด ์—ฐ์†์ ์ธ ๋ฐ”์ดํŠธ ๋‹จ์œ„์˜ ๋ฐ์ดํ„ฐ๋กœ ๊ฐ€๊ณตํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ง๋ ฌํ™”๋œ ๋ฐ์ดํ„ฐ๋Š” ๋ฐ˜๋Œ€๋กœ ์—ญ์ง๋ ฌํ™”(Deserialize)๋ฅผ ํ†ตํ•ด ๋‹ค์‹œ ์›๋ž˜์˜ ๋ฐ์ดํ„ฐ๋กœ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. XML ์ง๋ ฌํ™”๋Š” ์–ด๋–ค ๊ฐ์ฒด๋ฅผ XML ๋ฐ์ดํ„ฐ๋กœ ์ง๋ ฌํ™”ํ•˜์—ฌ ์ €์žฅ(๋˜๋Š” ์ „์†ก)ํ•˜๊ณ , ๋‹ค์‹œ ์ง๋ ฌํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋˜๋Œ๋ฆฌ๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ์˜ˆ์‹œ๋กœ ๋ณด์—ฌ์คฌ๋˜ ํ•™์ƒ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด XML ๊ตฌ์กฐ๋ฅผ ๊ฐ์ฒด๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

using System.Xml.Serialization;

namespace ExamXML
{
    [Serializable]
    [XmlRoot("Root")]
    public class School
    {
        [XmlElement("Class")]
        public List<Class> Classes { get; set; }
    }

    [Serializable]
    public class Class
    {
        [XmlAttribute("Name")]
        public string Name { get; set; }

        [XmlElement("Student")]
        public List<Student> Students { get; set; }
    }

    [Serializable]
    public class Student
    {
        [XmlAttribute("Index")]
        public int Index { get; set; }

        [XmlElement("Name")]
        public string Name { get; set; }

        [XmlElement("Phone")]
        public string Phone { get; set; }
    }
}

Serializable ํ‚ค์›Œ๋“œ๋Š” ๊ฐ์ฒด๊ฐ€ ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๊ณ , XmlRoot์™€ XmlElement๋Š” ๋…ธ๋“œ์˜ ์ด๋ฆ„, ๊ทธ๋ฆฌ๊ณ  XmlAttrinute๋Š” ์†์„ฑ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์ฒด๋ฅผ XML ์ง๋ ฌํ™”ํ•˜๊ธฐ

ํ•™์ƒ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด School ๊ฐ์ฒด๋ฅผ Xml ์ง๋ ฌํ™”ํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

private void btnSeiralize_Click(object sender, EventArgs e)
{
    try
    {
        var school = new School
        {
            Classes = new List<Class>
            {
                new Class
                {
                    Name = "A",
                    Students = new List<Student>
                    {
                        new Student { Index = 0, Name = "์ฒ ์ˆ˜", Phone = "010-xxxx-xxxx" },
                        new Student { Index = 1, Name = "์˜ํฌ", Phone = "010-yyyy-yyyy" }
                    }
                },
                new Class
                {
                    Name = "B",
                    Students = new List<Student>
                    {
                        new Student { Index = 0, Name = "์งฑ๊ตฌ", Phone = "010-zzzz-zzzz" },
                        new Student { Index = 1, Name = "๋งน๊ตฌ", Phone = "010-xxxx-yyyy" },
                        new Student { Index = 2, Name = "๊ธฐ์˜", Phone = "010-xxxx-zzzz" }
                    }
                }
            }
        };

        SaveFileDialog dlg = new SaveFileDialog();
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(School));
            using (FileStream fileStream = new FileStream(dlg.FileName, FileMode.Create))
            {
                serializer.Serialize(fileStream, school);
            }
        }
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}

๊ฐ์ฒด๋ฅผ XML ๊ตฌ์กฐ๋กœ ์ง๋ ฌํ™”ํ•  ๊ฒƒ์ด๋‹ˆ, ํ™•์žฅ์ž๋Š” XML๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ €์žฅ๋œ ํŒŒ์ผ์„ ์—ด์–ด๋ณด๋ฉด ์ฒ˜์Œ์— ์ œ์‹œํ•œ XML ํŒŒ์ผ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

XML ํŒŒ์ผ์„ ๊ฐ์ฒด๋กœ ์—ญ์ง๋ ฌํ™”ํ•˜๊ธฐ

์ด๋ฒˆ์—” ๋ฐ˜๋Œ€๋กœ, XML ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ค๋ฉด School ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

private void btnDeserialize_Click(object sender, EventArgs e)
{
    try
    {
        OpenFileDialog dlg = new OpenFileDialog();
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(School));
            using (FileStream fileStream = new FileStream(dlg.FileName, FileMode.Open))
            {
                School school = (School)serializer.Deserialize(fileStream);
            }
        }
    }
    catch (Exception exc)
    {
        MessageBox.Show(exc.Message);
    }
}

์œ„ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ด XML ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ค๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ์ฒด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

XML ํŒŒ์ผ๋กœ๋ถ€ํ„ฐ ๊ฐ์ฒด๋กœ ์—ญ์ง๋ ฌํ™”ํ•œ ๊ฒฐ๊ณผ

์ •๋ฆฌํ•˜๊ธฐ

๊ฐœ์ธ์ ์œผ๋กœ XML์€ ์ฃผ๋กœ ํ”„๋กœ๊ทธ๋žจ์˜ ์‹œ์Šคํ…œ ์„ค์ • ๊ฐ’์„ ๊ด€๋ฆฌํ•˜๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. INI๋ณด๋‹ค ์‚ฌ์šฉํ•˜๊ธฐ ํŽธํ•˜๊ณ  ์ง๋ ฌํ™”๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด ๊ด€๋ฆฌ๊ฐ€ ๋” ์šฉ์ดํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ, ์ง๋ ฌํ™”๋Š” XML๋งŒ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๊ณ  ์–ด๋–ค ๊ฐ์ฒด๋“  ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™”๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€ PropertyGrid ์ปจํŠธ๋กค๊ณผ XML ๊ฐ์ฒด๋ฅผ ์—ฐ๋™ํ•˜๋ฉด XML ํŽธ์ง‘์ด ๋”์šฑ ์šฉ์ดํ•˜๊ณ  ํ™œ์šฉ์„ฑ์ด ๋†’์•„์ง€๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ๋ฒˆ ์‚ฌ์šฉํ•ด ๋ณด์„ธ์š”.

ExamXML.zip
0.01MB

๋ฐ˜์‘ํ˜•