เลือกโหนดเฉพาะใน XML ด้วย LINQ

ฉันกำลังเขียนฟังก์ชันที่โหลดและเอกสาร XML แล้วแปลงเป็น CSV เนื่องจากฉันต้องการเพียงบางค่าจากไฟล์ XML เป้าหมายที่ฉันพยายามทำให้สำเร็จคือการเลือกเฉพาะโหนดที่ฉันสนใจ

นี่คือรหัสของฉัน:

      XDocument csvDocument = XDocument.Load(tempOutput);

        StringBuilder csvBuilder = new StringBuilder(1000);

        foreach (XElement node in csvDocument.Descendants("Sample"))
        {
            foreach (XElement innerNode in node.Elements())
            {
                        csvBuilder.AppendFormat("{0},", innerNode.Value);
                    }

                    csvBuilder.Remove(csvBuilder.Length -1, 1);

                    csvBuilder.AppendLine();
                }
                csvOut = csvBuilder.ToString();

แต่ด้วยวิธีนี้ ฉันจะเลือกโหนดย่อยทั้งหมดภายในโหนด "ตัวอย่าง"

ใน XML ต้นไม้ "ตัวอย่าง" คือ:

<Sample Type="Object" Class ="Sample">
    <ID>1</ID>
    <Name>10096</Name>
    <Type>2</Type>
    <Rep>0</Rep>
    <Selected>True</Selected>
    <Position>1</Position>
    <Pattern>0</Pattern>
   </Sample>

รหัสทำงานได้อย่างไร้ที่ติ แต่ฉันต้องการเพียง "ID" และ "Selected" เท่านั้นที่จะเลือก และค่าของรหัสเหล่านั้นเขียนอยู่ในไฟล์ CSV

ใครช่วยชี้ฉันในทิศทางที่ถูกต้องได้ไหม?

ขอบคุณ.


person user1776401    schedule 30.03.2013    source แหล่งที่มา
comment
แล้วคุณต้องการทำอะไร {ID},{Name} และอื่นๆ สำหรับทุกออบเจ็กต์ตัวอย่าง   -  person It'sNotALie.    schedule 31.03.2013


คำตอบ (1)


เรียนรู้เพิ่มเติมเกี่ยวกับ Linq-to-xml ที่นี่ คุณไม่ได้ จริงๆ ใช้ประโยชน์จาก 'linq-edness' ของ XObjects

var samples = csvDocument.Descendants("Sample")
                         .Select(el => new {
                             Id = el.Element("ID").Value,
                             Selected = el.Elemnt("Selected").Value
                         });

สิ่งนี้จะสร้าง IEnumerable<T> ให้คุณโดยที่ 'T' เป็นประเภทที่ไม่ระบุตัวตนด้วย คุณสมบัติ Id และ Selected คุณสามารถแยกวิเคราะห์ (int.Parse หรือ bool.Parse) รหัสและค่าที่เลือกเพื่อความปลอดภัยของประเภท แต่เนื่องจากคุณเพียงแค่เขียนถึงวัตถุ StringBuilder คุณอาจไม่สนใจ ...แค่ FYI

วัตถุ StringBuilder นั้นสามารถเขียนได้ดังนี้:

foreach (var sample in samples) {
    csvBuilder.AppendFormat(myFormattedString, sample.Id, sample.Selected);
}

ข้อแม้คือวัตถุที่ไม่ระบุชื่อของคุณและลูป for-each ควรอยู่ในขอบเขตเดียวกัน แต่มีวิธีแก้ไขหากจำเป็น

เช่นเคย การถลกหนังแมวมีมากกว่าหนึ่งวิธี

อัปเดต ...ในการอ้างอิง แสดงความคิดเห็น:

foreach (XElement node in csvDocument.Descendants("Sample"))
{
    foreach (XElement innerNode in node.Elements())
    {
        //    this logic assumes different formatting for values
        //    otherwise, change if statement to || each comparison
        if(innerNode.Name == "ID") {
            // append/format stringBuilder
            continue;
        }

        if(innerNode.Name == "Selected") {
            // append/format stringBuilder
            continue;
        }
    }

    csvBuilder.Remove(csvBuilder.Length -1, 1);

    csvBuilder.AppendLine();
}
person IAbstract    schedule 30.03.2013
comment
แน่นอนว่าฉันก็ต้องลองวิธีนี้เหมือนกัน แต่ฉันอยากไปแบบที่ฉันเขียนไว้แล้ว ควรมีวิธีแก้ไข: foreach (XElement innerNode ใน node.Elements()) เพิ่มกฎบางอย่างเพื่อข้ามองค์ประกอบที่ไม่ต้องการหรือใช้เฉพาะสิ่งที่ฉันต้องการ - person user1776401; 31.03.2013
comment
ใน foreach ของคุณ ให้ตรวจสอบชื่อ innerNode และหากไม่ใช่ ID หรือ Selected ให้ข้ามไปใช่ไหม หรือฉันขาดอะไรบางอย่างไป? - person Pete; 31.03.2013
comment
ขอบคุณ IAabstract! รหัสของคุณใช้งานได้! ก่อนที่ฉันจะลองต่อท้าย innerNode.Name เข้ากับคำสั่ง foreach แต่มันทำให้ฉันมีข้อผิดพลาด! ขอบคุณอีกครั้ง. อย่างไรก็ตาม พีท ฉันก็ลองวิธีนี้เช่นกัน โดยเพิ่มคุณสมบัติ Skip ให้กับคำสั่ง foreach แต่ฉันต้องทำบางอย่างผิดเพราะมันใช้งานไม่ได้ คุณช่วยโพสต์ตัวอย่างการทำงานได้ไหม? - person user1776401; 31.03.2013