PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net | XML + LINQ

XML정보와 LINQ..

DataTable개체이야기는 LINQ가 아닌 DataTable개체를 별도로 페이지를 마련하고
다시 하도록 하고,
XML화일에 대한 질문이 있었다
LINQ와는 좀 다른 별개의 문제였지만, LINQ와 관련없는 문제도 풀고
더불어 XML화일의 정보를 LINQ로 분석도 할수 있다는 것을 볼수 있는 좋은 기회의 문제였기때문에
올려 놓도록 하자
물론 XML관련 일반적인 것은 XML 관련페이지에서 별도로 또 다루도록 하고..

문제는 이런 것이였다
XML관련 개체로 XML문서를 작성하여 문서를 작성하지 않고
문자열로 TextBox콘트롤에 담고
이 TextBox의 문자열 정보를 받아서 목록상자에 별도의 다른 정보로
만들려고 하였던 내용이다
실험정신이 좋으시다
대개의 XML화일은 외부에서 화일을 읽어서 작업을 하는 것이 대부분이지만..
TextBox에 써진 내용을 한번 분석하시고 싶었던 것이다



XML문서의 내용을 그대로 TextBox에 올려 놓으면..
보기에는 똑같아 보이지만, TextBox라는 그릇속에서 보이지 않는 정보의
찌꺼기가 묻어서.. XML문서를 제대로 이해못하고 에러를 낸다
마치 엑셀에서도 시트상에 똑같아 보이는 정보인데,
분석을 할때 읽지 못하고 엉뚱한 에러가 나는 경우가 많은 것과 같은 것일 것이다
왜 어떤 정보가 보이지 않게 숨어있는지 찾는 것 보다는
방법을 바꾸면 된다

Dim settings As New XmlWriterSettings()
settings.Encoding = Encoding.UTF8
settings.ConformanceLevel = ConformanceLevel.Document
settings.Indent = True
Dim memoryStream As New MemoryStream()
Dim writer As XmlWriter = XmlWriter.Create(memoryStream, settings)
....
....
....
와 같이 메모리상에 XML화일을 작성하고
이것을 다시 읽어서 TextBox에 문자열로 나타나게 한 것

위의 내용을 모두 똑같이 하고 한줄만 바꾸자

Dim writer As XmlWriter = XmlWriter.Create("test.xml", settings)

메모리개체에 넣지 않고 임시 xml화일을 만드는 것으로..
이렇게 임시 화일이 만들어지는 것은 프로젝트의 Debug 폴더에 화일이 만들어지는 것

아무튼 별실무적으로 필요한 것은 아니지만, 질문하신분의 실험정신에 부응하기 위하기 위한것이고..

이페이지에서 하고자 하는 것은..
어떻게 XML화일의 정보를 구성하던(외부에서 화일을 불러오던,메모리에 있는 정보던), 상관없이
이 정보에서 LINQ를 사용하여 데이타를 분석하는 것이
이페이지의 목적이다

XML문서이던, DataTable에 들어있는 정보이던, 엑셀의 시트에 뿌려져있는 정보이던
모두 정보는 집합체들이다..
같은 타입의 정보가 줄줄이 들어 있는 것이고, 이것은 집합체이고..
그러니 집합체의 정보를 분석을 하려면 순환문은 필수적이고..
이런 다양한 형태의 정보를 좋은 분석언어를 하나 마련하여
데이타베이스에서 와서 DataTable에 들어 있는 정보이던..
XML 형식의 문서이던, 모두 풀수 있다면 다양한 형식의 정보마다 새로운 방식으로
분석을 하여야 하는 노력이 절약되는 것이고..그래서 LINQ가 있는 것이고
XML문서를 분석하려면 XML문서를 파싱하는 다양한 개체가 준비되어 있다
LINQ를 사용하여 XML문을 분석하려면..아래의 그림과 같이
System.XML.LINQ NameSpace에서 XElement 를 택하면 된다




XElement로 TextBox에 기록된 XML문을 그대로 읽어서
아래와 같이 LINQ로 분석을 할수 있다

질문하신분은 전통적 방식으로 값을 찾아서 처리하지만
이곳은 LINQ를 익히는 곳이니, LINQ로 분석한다

Try
    ''TextBox정보를 문자열로 받아서
    Dim sXML As String = Me.TextBox1.Text
    ''StringReader로 문자열을 받아서 XMLTextReader로 XML형식으로 유지하여
    ''XElement개체로 로딩하면 LINQ로 처리할수 있는 집합체가 된셈이다
    Dim oXML As XElement = XElement.Load(New System.Xml.XmlTextReader(New System.IO.StringReader(sXML)))
    ''아래와 같이 LINQ문으로 처리하다..
    Dim Q = From X In oXML.Elements
            Select A = X.Elements("name"), B = X.Elements("amount")

     ''ListBox의 DataSource에 주기위하여 List개체에 다시 담고..
    Dim oList As New List(Of String)
    For iX As Integer = 0 To Q.Count - 1
        oList.Add(Q(iX).A.Value & " " & Q(iX).B.Value)
    Next
    Me.ListBox1.DataSource = oList
Catch ex As Exception

End Try

   

요약값을 얻는 작업을 하고 싶다면 아래와 같이

Dim Q = From X In oXML.Elements
        Select New With {.A = X.Elements("name"), .B = X.Elements("amount")}


Dim oList As New List(Of String)
oList.Add("합계   " & Q.Sum(Function(x) x.B.Value))
oList.Add("평균   " & Q.Average(Function(x) x.B.Value))
oList.Add("최대   " & Q.Max(Function(x) x.B.Value))
oList.Add("최소   " & Q.Min(Function(x) x.B.Value))
oList.Add("수량   " & Q.Count)
  

위에서 갯수는 그냥 집합체에 Count메소드를 붙이면 되는데
왜 다른 것들은 Q.Max(Function(x) x.B.Value)
와 같이 해야 할까???
Count는 그냥 단순히 집합체의 갯수이니까..그냥 Count만 붙여도 된다
하지만 다른 것은 숫자를 계산해야 하는 것..LINQ로 얻어낸 집합체는 A값과 B값이라는
두개의 값을 갖고 있는 것이다, 즉 어떤 값으로 계산할것인지 매개변수를 전달하여야 하니까..
앞에서 학습한 Delegate개체를 전달하는 것이고..Delegate개체를 매개변수를 전달하는 곳에서는
Lambda Expression이 될수 있는 것이고..그래서 Lambda Expression 이 매개변수로
전달 된 것

하나 비교해보자 아래와 같은 경우는 그냥 Extension 메소드 Sum을 그대로 사용해도 된다

        Dim Q = From X In New Integer() {1, 2, 3, 4, 5, 6, 7}
            Select X

        MsgBox Q.Sum()

앞에서 한참 이야기했던 페이지를 다시 또 보시면
죄다 이해가 될 것이다

아래 화일을 보시면, XML이라는 것도 참 편리한것이고,또한 LINQ는 정말 전천후 분석도구라는 것을
그래서 꼭 알고 챙겨야 할 것이라는 것을 실감하실 것이다
LINQ-1,LINQ-2코너를 통하여
LINQ에 관한 것과 LINQ를 알기 위한 기초적인 NetFrameWork의 다양한 개체를
살펴보았다
이제 다른 코너를 통하여 LINQ를 활용하면서 NetFrame의 자원을 활용하도록 하자

***[LOG-IN]***