MSDN - ระบบ Xml.XPath Extensions Class พูดว่า:
มีโทษด้านประสิทธิภาพบางประการสำหรับการใช้วิธีการเหล่านี้ การใช้ LINQ กับแบบสอบถาม XML ให้ประสิทธิภาพที่ดีขึ้น
และ XPathSelectElement เป็นวิธีการขยาย
ฉันมี XML ต่อไปนี้ ฉันจำเป็นต้องค้นหาข้อความและเชื่อมต่อเข้าด้วยกัน ความท้าทายคือ - ฉันต้องเลือกเฉพาะข้อความที่อยู่ภายใต้ Status/StatusMsg/StatusDetail
ด้วย Descendants
ฉันได้รับข้อความทั้งหมด แม้จะอยู่นอกองค์ประกอบที่จำเป็นก็ตาม
ซึ่งสามารถทำได้อย่างถูกต้องโดยใช้ XPathSelectElement
แต่เนื่องจาก XPathSelectElement เป็นวิธีส่วนขยาย จึงมีประสิทธิภาพบางอย่างดังที่แสดงใน LINQ to XML พร้อมการตรวจสอบประสิทธิภาพ XPath ซึ่งระบุว่า:
ในกรณีส่วนใหญ่ การเรียกใช้แบบสอบถาม XPath จะส่งผลให้มีระยะเวลาการดำเนินการนานกว่าการสืบค้นโดยใช้ LINQ มาตรฐานเป็น XML ถึง 5 เท่า
วิธีที่ดีที่สุดที่จะทำโดยไม่ใช้วิธีการขยายใน LINQ ถึง XML โดยใช้ C # คืออะไร
หมายเหตุ: มีวิธีปรับแต่ง Descendants
เพื่อจุดประสงค์นี้หรือไม่
XML
XDocument xDoc = XDocument.Parse(@"
<Status>
<StatusMsg>
<StatusType>INVOICE</StatusType>
<StatusDetail>
<Sequence test=""K""> 2 </Sequence>
<Message>A</Message>
</StatusDetail>
<StatusDetail>
<Message>B</Message>
</StatusDetail>
<StatusDetail>
<Message>C</Message>
</StatusDetail>
</StatusMsg>
<StatusDetail>
<Message>OUTSIDE</Message>
</StatusDetail>
</Status>
");
รหัส
// Descendants
var messageArrayWithOutside = xDoc.Descendants(@"StatusDetail")
.Select(
x => x.Element("Message") == null ? String.Empty : x.Element("Message").Value.Trim()
).ToArray();
var textAll = string.Join(", ", messageArrayWithOutside);
//XPathSelectElements
var messageArray = xDoc.XPathSelectElements(@"Status/StatusMsg/StatusDetail")
.Select(
x => x.Element("Message") == null ? String.Empty : x.Element("Message").Value.Trim()
).ToArray();
var text = string.Join(", ", messageArray);
อัปเดต
XPath ดูเหมือนจะเร็วกว่าการใช้ Descendants สองครั้ง มีความคิดว่าทำไม?
// Descendants
Stopwatch stopWatchDescendants = new Stopwatch();
stopWatchDescendants.Start();
var messageArrayDecendants = xDoc.Descendants("StatusMsg")
.Descendants("StatusDetail")
.Select(
x => x.Element("Message") == null ?string.Empty : x.Element("Message").Value.Trim()
).ToArray();
var textDecendants = string.Join(", ", messageArrayDecendants);
stopWatchDescendants.Stop();
TimeSpan tsDescendants = stopWatchDescendants.Elapsed;
//XPathSelectElements
Stopwatch stopWatchXPath = new Stopwatch();
stopWatchXPath.Start();
var messageArrayXPath = xDoc.XPathSelectElements(@"Status/StatusMsg/StatusDetail")
.Select(
x => x.Element("Message") == null ? String.Empty : x.Element("Message").Value.Trim()
).ToArray();
var textXPath = string.Join(", ", messageArrayXPath);
stopWatchXPath.Stop();
TimeSpan tsXPath = stopWatchXPath.Elapsed;
if (tsXPath > tsDescendants)
{
Console.WriteLine("LINQ is fast");
}
if (tsDescendants > tsXPath)
{
Console.WriteLine("XPath is fast");
}
Console.WriteLine("XPath :" + tsXPath.ToString());
Console.WriteLine("LINQ :" + tsDescendants.ToString());