2

C# を使用して比較的複雑な XML ファイルを解析し、選択したデータを SQL Server '08 データベースに格納しようとしています。これは、XML ファイルから抽出しようとしているものです。

<educationSystem>
    <school>
        <name>Primary School</name>
        <students>
            <student id="123456789">
                <name>Steve Jobs</name>
                <other elements>More Data</other elements>
            </student>
            <student id="987654">
                <name>Jony Ive</name>
                <otherElements>More Data</otherElements>
            </student>
        </students>
    </school>
    <school>
        <name>High School</name>
        <students>
            <student id="123456">
                <name>Bill Gates</name>
                <other elements>More Data</other elements>
            </student>
            <student id="987654">
                <name>Steve Ballmer</name>
                <otherElements>More Data</otherElements>
            </student>
        </students>
    </school>
</educationSystem>

[質問する前に、いいえ、これは学校の課題ではありません。学校/学生を例として使用しています。オリジナルはよりデリケートなためです。]

(XDocument/XElement を使用して) XML ファイルを解析し、すべての学校名、学生名、および学生 ID のリストを取得できますが、これがデータベースに追加されると、Bill Gates学生のエントリが 1 秒未満になります。学校。それはすべて行ごとです。

私は、これを達成する方法を探しています:

Foreach school
    put it's name into an XElement
    foreach student
        grab the name and id put into XElements
Grab next school and repeat

これを達成するにはLinqが最善の方法だと思いますが、プロセスを開始する方法に問題があります。誰かが私を正しい方向に向けることができますか?

編集:データをデータベースに保存するために現在使用しているコードは次のとおりです。一度にリストを処理します (したがって、物事は本来あるべきように関連していません)。また、SQL も整理します。

 private void saveToDatabase (List<XElement> currentSet, String dataName)
    {
        SqlConnection connection = null;

        try
        {
            string connectionString = ConfigurationManager.ConnectionStrings["connString"].ConnectionString + "; Asynchronous Processing=true";
            connection = new SqlConnection(connectionString);
            connection.Open();

            foreach (XElement node in currentSet)
            {
                SqlCommand sqlCmd = new SqlCommand("INSERT INTO dbo.DatabaseName (" + dataName + ") VALUES ('" + node.Value + "')", connection);

                sqlCmd.ExecuteNonQuery();
            }
        }
4

3 に答える 3

1

このLINQは、2つのプロパティを持つオブジェクトのコレクションを生成します

  1. 学校名

  2. 学生のリスト(再びコレクション)

     var result = XElement.Load("data.xml")
                   .Descendants("school")
                   .Select( x => new { 
                             name = XElement.Parse(x.FirstNode.ToString()).Value,
                             students =x.Descendants("student")
                                        .Select(stud => new { 
                   id = stud.Attribute("id"),
                   name = XElement.Parse(stud.FirstNode.ToString()).Value})
               .ToList()});
    

    注:LINQは、タグ<name>の下の最初のノードとして想定します<school><student>

  3. 次に、意図したforeachを使用でき、チャームのように機能します

     foreach (var school in result)
     {
        var schoolName = school.name;
        foreach (var student in school.students)
        {
                //Access student.id and student.name here                    
        }
     }
    
于 2012-11-09T15:02:21.427 に答える
0

更新:元のコード例では名前空間について言及されていませんでした。名前空間は、XNameで要素を検索するときに考慮する必要があるか、XName.LocalNameプロパティを使用して検索する必要があります。このような場合に要素の選択を処理する方法を示すために、例を更新しました。

namespace Stackover
{
    using System;
    using System.Xml.Linq;

    class Program
    {
        private const string Xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<namespaceDocument xmlns=""http://www.namedspace/schemas"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:schemaLocation=""http://www.namedspace/schemas.xsd"">
<educationSystem>
    <school>
        <name>Primary School</name>
        <students>
            <student id=""123456789"">
                <name>Steve Jobs</name>
                <otherElements>
                    <dataA>data</dataA>
                </otherElements>
            </student>
            <student id=""987654"">
                <name>Jony Ive</name>
                <otherElements>
                    <dataB>data</dataB>
                </otherElements>
            </student>
        </students>
    </school>
    <school>
        <name>High School</name>
        <students>
            <student id=""123456"">
                <name>Bill Gates</name>
                <otherElements>
                    <dataC>data</dataC>
                </otherElements>
            </student>
            <student id=""987654"">
                <name>Steve Ballmer</name>
                <otherElements>
                    <dataD>data</dataD>
                </otherElements>
            </student>
        </students>
    </school>
</educationSystem>
</namespaceDocument>";


        static void Main(string[] args)
        {
            var root = XElement.Parse(Xml);
            XNamespace ns = "http://www.namedspace/schemas";
            foreach(var school in root.Descendants(ns + "school")) // or root.Descendants().Where(e => e.Name.LocalName.Equals("school"));
            {
                Console.WriteLine(school.Element(ns + "name").Value);

                foreach (var students in school.Elements(ns+ "students"))
                {

                    foreach (var student in students.Elements())
                    {
                        Console.WriteLine(student.Attribute("id"));
                        Console.WriteLine(student.Name); // Name = namespace + XName
                        Console.WriteLine(student.Name.LocalName); // no namespace
                    }
                }
            }
        }

    }

}
于 2012-11-09T14:56:20.417 に答える