2009-08-04 5 views
1

안녕하세요 우연 StackOverflowers,.NET에서 문자열의 XML을 구문 분석하는 방법은 무엇입니까?

내 .NET 함수 중 하나에서 문자열을 수신하고 있습니다. 는 XML 비주얼에서 볼 문자열은 다음과 같습니다 : 나는 누구의 열 각 데이터에 대한 XML 태그입니다 데이터 테이블에 데이터를 쓸 수 있도록

- <root> 
- <Table> 
    <ID>ABC-123</ID> 
    <CAT>Housekeeping</CAT> 
    <DATE>21-JUN-2009</DATE> 
    <REP_BY>John</REP_BY> 
    <LOCATION>Head Office</LOCATION> 
</Table> 
- <Table> 
    <ID>ABC-124</ID> 
    <CAT>Environment</CAT> 
    <DATE>23-JUN-2009</DATE> 
    <REP_BY>Michelle</REP_BY> 
    <LOCATION>Block C</LOCATION> 
</Table> 
- <Table> 
    <ID>ABC-125</ID> 
    <CAT>Staging</CAT> 
    <DATE>21-JUN-2009</DATE> 
    <REP_BY>George</REP_BY> 
    <LOCATION>Head Office</LOCATION> 
</Table> 
- <Table> 
    <ID>ABC-123</ID> 
    <CAT>Housekeeping</CAT> 
    <DATE>21-JUN-2009</DATE> 
    <REP_BY>John</REP_BY> 
    <LOCATION space="preserve" xmlns="http://www.w3.org/XML/1998/namespace" /> 
</Table> 
</root> 

내가이 문자열을 구문 분석 할 필요가있다.

위의 텍스트에서 필자는 ID, CAT, DATE, REP_BY 및 LOCATION이라는 5 개의 열이 있고 그 다음 4 개의 데이터 행을 포함하는 datatable을 갖게됩니다.

네 번째 태그에는 해당 데이터가 없지만 space = "preserve"로 표시되어 있습니다. 이것은 내 데이터 테이블에 배치 할 데이터가 네 번째 행의 LOCATION 열에 대해 비어 있음을 의미합니다.

어떻게하면됩니까? 샘플 코드는 매우 높이 평가 될 것입니다. 감사.

+0

당신은 C#을 사용한다고 가정합니다. 어떤 버전을 사용합니까? –

+0

.NET 버전 2.0 – Batuta

답변

4

아마도 XML을 테이블 형식으로 가져 오는 가장 간단한 솔루션 일 것입니다. 특성을 일반 표현식을 사용하여 던지는 것은 똑똑하고 안전하지는 않지만 System.Xml API를 좋아하지 않으며 XML에 대한 LINQ는 .NET 2.0에서 옵션이 아닙니다.

using System; 
using System.Data; 
using System.IO; 
using System.Text.RegularExpressions; 

namespace GeneralTestApplication 
{ 
    class Program 
    { 
     private static void Main() 
     { 
      String input = @"<root><Table> [...] </root>"; 

      input = Regex.Replace(input, @" [a-zA-Z]+=""[^""]*""", String.Empty); 

      DataSet dataSet = new DataSet(); 

      dataSet.ReadXml(new StringReader(input)); 

      foreach (DataRow row in dataSet.Tables[0].Rows) 
      { 
       foreach (DataColumn column in dataSet.Tables[0].Columns) 
       { 
        Console.Write(row[column] + " | "); 
       } 
       Console.WriteLine(); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 

UPDATE

또는이 System.Xml를 사용하여 속성을 제거. 마지막 LOCATION 요소의 XML 네임 스페이스가 남아 있고 DataSet.LoadXml()이 connot LOCATION라는 두 개의 열이있을 불평 때문에

XmlDocument doc = new XmlDocument(); 

doc.Load(new StringReader(input)); 

foreach (XmlNode node in doc.SelectNodes("descendant-or-self::*")) 
{ 
    node.Attributes.RemoveAll(); 
} 

input = doc.OuterXml; 

는하지만이 작동하지 않습니다.

+0

나는 왜 누군가가이 대답을 슬퍼 할 지 모른다. RegEx를 사용하여 소스 문자열을 치료 하시겠습니까? 심지어 화이트 핫 열정으로 XML에서 문자열 처리를 사용하는 것을 싫어하는 나는 이것을 할 수도있다. –

+0

이것이 내가 얻은 경우를 특히 해결하는 데 도움이 되었기 때문에 이것을 답변으로 썼습니다. – Batuta

1

문자열 구문 분석을 사용하지 마십시오. 일부 XML 라이브러리 (Linq)에 도움이되는 몇 가지 객체가 있습니다. 아마 그렇게 쉽게 할 수있을 것입니다.

+0

LINQ 외 다른 방법은 없습니까? .NET 2.0을 사용하고 있기 때문에 LINQ를 사용할 수 없습니다. 감사. – Batuta

+0

오, 알겠습니다. 그렇다면 프란시스가 더 도움이 될 것입니다. 그러나 일부 .NET 3.5이이 질문을 발견하는 경우를 대비하여) –

8

XmlReader 클래스 사용 이 클래스는 빠르며 많은 메모리를 사용하지 않지만 xml을 읽는 것은 어려울 수 있습니다.

using (StringReader strReader = new StringReader(yourXMLString)) 
{ 
    using (XmlReader reader = XmlReader.Create(strReader)) 
    { 
     while (reader.Read()) 
     { 
      if(reader.Name == "Table" && reader.NodeType == reader.NodeType == XmlNodeType.Element) 
      { 
       using(XmlReader tableReader = reader.ReadSubtree()) 
       { 
        ReadTableNode(tableReader); 
       } 
      } 
     } 
    } 
} 

private void ReadTableNode(XmlReader reader) 
{ 
    while (reader.Read()) 
    { 
     if(reader.Name == "ID" && reader.NodeType == reader.NodeType == XmlNodeType.Element) 
      //do something 
     else if(reader.Name == "CAT" && reader.NodeType == reader.NodeType == XmlNodeType.Element) 
      //do something 

     //and continue.... 
    } 
} 

은 사용하는 현재 노드의 속성을 가져 오려면 다음을

string value = reader.GetAttribute(name_of_attribute); 

가 요소의 내부 텍스트를 얻으려면 :

string innerText = reader.ReadString(); 

XMLDocument 클래스를 사용하여. 이 클래스는 느리지 만 전체 XML이로드되기 때문에 XML을 조작하고 읽는 것은 매우 쉽습니다.

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml(yourXMLString); 
//do something 

XDocument 클래스 사용 XDocument를 사용하면 요소를 직접 및 동시에 액세스 할 수 있다는 이점이 있습니다. 이 클래스는 LINQ 기능을 사용하여 XML 문서를 쿼리합니다.

using(StringReader tr = new StringReader(yourXMLString)) 
{ 
    XDocument doc = XDocument.Load(tr); 
    //do something 
} 
+0

문자열의 데이터를 기반으로 데이터 테이블의 열 이름을 어셈블하는 방법은 무엇입니까? – Batuta

+0

게시 한 실제 문자열 데이터를 사용하여 더 많은 코드 예제를 제공해 주시겠습니까? 귀하의 코드를 시도했지만 아무 것도 내 xmlreader 변수에 나타나지 않습니다. 감사합니다. . – Batuta

+0

코드 샘플을 업데이트했습니다. –

2

편도와 다름을 사용하는 데는 장단점이 있습니다.

XML을 앞뒤로 건너 뛰고 다른 요소에 무작위로 액세스하는 방법을 찾고 있다면 XmlDocument를 사용합니다.

XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xmlVariable); 

그런 다음 당신은 다음과 같이 사용할 수 있습니다 (귀하의 XML을 가정 할 문자열에있을 수 있습니다) : XPath에 대해

XmlNodeList xmlNodes = doc.SelectNodes(xPathString); 

구글을 당신이 방법에 대한 좋은 기사를 찾을 수 있습니다 문서의 특정 요소로 이동 한 후 다음과 같이 반복 할 수 있습니다.

foreach(XmlNode node in xmlNodes) 
{ 
    // do something with node.InnerText or any other property/method that you like 
    // also through this method you can access the attributes of each node 
    // allowing you to process that last LOCATION elements attributes 
} 

xml이 어딘가에 파일에 있으면 doc.Load (filename) 또는 스트림 객체를 선택하여로드 할 수 있습니다.

이제까지 한 번만 구문 분석하고 XML 문자열이 거대한 경우 "전달 전용"이기 때문에 훨씬 빨라서 StringReader/XmlReader를 제안합니다. 이는 정확한 용어는 아니지만 모든 문서를 한 번에 저장할 필요가 없기 때문에 메모리 사용량을 줄입니다.

+0

앞서 언급했듯이 문자열을 한 번만 파싱하고 데이터 테이블에 데이터를 가져와야합니다.우연히도 datatable 열 필드는 문자열 (XML?) 데이터의 필드와 같아야합니다. 감사합니다. – Batuta

0

난 당신이 단순히 형식으로 XML 문서를 읽을 수있는 ADO.NET DataSet 클래스의 ReadXml 방법을 사용할 수 있습니다, 그것은 당신을 위해 DataTable, DataColumnDataRow 개체를 만들 것이라고 믿는다. 나중에 DATE 열의 데이터 형식을 DateTime으로 바꾸려면 약간의 변환 방법을 사용해야합니다. 하지만 그 외에는 XML을 사용하지 않아도됩니다.

편집 내가 이상한 공간에서 위치 요소가 문제를 제기 다니엘 브루크너의 게시물에서 볼

. 글쎄, 그건 쉽게 해결 충분 :

XmlDocument d = new XmlDocument(); 
    d.LoadXml(xml); 

    XmlNamespaceManager ns = new XmlNamespaceManager(d.NameTable); 
    ns.AddNamespace("n", "http://www.w3.org/XML/1998/namespace"); 
    foreach (XmlNode n in d.SelectNodes("/root/Table/n:LOCATION", ns)) 
    { 
     XmlElement loc = d.CreateElement("LOCATION"); 
     n.ParentNode.AppendChild(loc); 
     n.ParentNode.RemoveChild(n); 
    } 

    DataSet ds = new DataSet(); 
    using (StringReader sr = new StringReader(d.OuterXml)) 
    { 
     ds.ReadXml(sr); 
    } 
0

나 자신을 XML의 거대한 팬이 아니에요, 나는 그것을 시각화하는 그리드의 데이터 소스로 사용합니다. XML 형식의 FileNet 이미징 서버에서 일부 출력을 얻었으므로 데이터베이스를 채우기 위해 일부만 가져와야합니다. 다음은 내가하는 일입니다. HTH :

Dim dsXML As DataSet 
    Dim drXML As DataRow 
    Dim rdr As System.IO.StringReader 
    Dim docs() As String 
    Dim SQL As String 
    Dim xml As String 
    Dim fnID As String 

docs = _fnP8Dev.getDocumentsXML(_credToken, _docObjectStoreName, _docClass, "ReferenceNumber=" & fnID, "") 
xml = docs(0) 
If (InStr(xml, "<z:row") > 0) Then 
RaiseEvent msg("Inserting images for reference number " & fnID) 
rdr = New System.IO.StringReader(xml) 
dsXML = New DataSet 
dsXML.ReadXml(rdr) 

For Each drXML In dsXML.Tables(dsXML.Tables.Count - 1).Rows 
    SQL = "Insert into fnImageP8 values (" 
    SQL = SQL & "'" & drXML("Id") & "', " 
    Try 
    SQL = SQL & "'" & drXML("DocumentTitle") & "', " 
    Catch ex As Exception 
    SQL = SQL & "null, " 
    End Try 
관련 문제