将XML加载到XDocument中的最快方法是什么?

使用XDocument.Load创建新的XDocument时,它是打开XML文件并保留本地副本,还是从硬盘连续读取文档?如果它连续读取,有没有更快的方法来解析XML

XDocument x=XDocument.Load(“file.xml”);

有两种测量方法需要考虑:

  1. 线性遍历速度(例如读取/加载)
  2. 按需查询速度

要回答眼前的问题:XDocument使用XmlReader读取每个元素并创建相应的XElement实例,将文档加载到内存中(请参见下面的代码)。因此,它应该相当快(对于大多数目的来说足够快),但在解析大型文档时可能会消耗大量内存

如果您的需求仅限于无需将文档保留在内存中即可完成的内容,那么原始XmlReader是遍历的最佳选择。它的性能优于其他方法,因为与其他节点(例如链接父节点和子节点)的关系不会创建或解析重要结构。然而,按需查询能力几乎不存在;您可以对每个节点中的值作出反应,但不能作为一个整体查询文档。如果需要再次查看文档,则必须再次遍历整个文档

相比之下,XDocument将需要更长的时间来遍历,因为它实例化新对象并执行基本的结构化任务。它还将消耗与源大小成比例的内存。作为这些权衡的交换,您将获得出色的查询能力

正如Jon Skeet所提到并在这里展示的那样,可以组合这些方法:使用C#自定义迭代器和XmlReader将数据流传输到LINQ到XML

XDocument Load()的源文件

公共静态XDocument加载(流、加载选项)
{
XmlReaderSettings XmlReaderSettings=XNode.GetXmlReaderSettings(选项);
xD文档结果;
使用(XmlReader=XmlReader.Create(流,xmlReaderSettings))
{
结果=XDocument.Load(xmlReader,选项);
}
返回结果;
}
//这叫。。。
公共静态XDocument加载(XmlReader、加载选项)
{
如果(读卡器==null)
{
抛出新的异常(“读取器”);
}
if(reader.ReadState==ReadState.Initial)
{
reader.Read();
}
XDocument XDocument=新XDocument();
if((options&LoadOptions.SetBaseUri)!=LoadOptions.None)
{
字符串baseURI=reader.baseURI;
if(baseURI!=null&baseURI.Length!=0)
{
xDocument.SetBaseUri(baseURI);
}
}
if((options&LoadOptions.SetLineInfo)!=LoadOptions.None)
{
IXmlLineInfo xmlLineInfo=读卡器为IXmlLineInfo;
if(xmlLineInfo!=null&xmlLineInfo.HasLineInfo())
{
xDocument.SetLineInfo(xmlLineInfo.LineNumber,xmlLineInfo.LinePosition);
}
}
if(reader.NodeType==XmlNodeType.XmlDeclaration)
{
xDocument.Declaration=新XDeclaration(读卡器);
}
xDocument.ReadContentFrom(阅读器,选项);
if(!reader.EOF)
{
抛出新的InvalidOperationException(Res.GetString(“InvalidOperation_ExpectedEndOfFile”);
}
if(xDocument.Root==null)
{
抛出新的InvalidOperationException(Res.GetString(“InvalidOperation_MissingRoot”);
}
返回xDocument;
}
//这叫。。。
内部void ReadContentFrom(XmlReader r,LoadOptions o)
{
if((o&(LoadOptions.SetBaseUri | LoadOptions.SetLineInfo))==LoadOptions.None)
{
这个.ReadContentFrom(r);
回来
}
if(r.ReadState!=ReadState.Interactive)
{
抛出新的InvalidOperationException(Res.GetString(“InvalidOperation_ExpectedInteractive”);
}
XContainer XContainer=此;
XNode XNode=null;
NamespaceCache NamespaceCache=默认值(NamespaceCache);
NamespaceCache namespaceCache2=默认值(NamespaceCache);
字符串文本=((o&LoadOptions.SetBaseUri)!=LoadOptions.None)?r.BaseURI:null;
IXmlLineInfo xmlLineInfo=((o&LoadOptions.SetLineInfo)!=LoadOptions.None)?(r为IXmlLineInfo):空;
while(true)
{
字符串baseURI=r.baseURI;
开关(r.NodeType)
{
case XmlNodeType.Element:
{
XElement-XElement=new-XElement(namespaceCache.Get(r.NamespaceURI.GetName)(r.LocalName));
if(text!=null&text!=baseURI)
{
SetBaseUri(baseURI);
}
if(xmlLineInfo!=null&xmlLineInfo.HasLineInfo())
{
xElement.SetLineInfo(xmlLineInfo.LineNumber,xmlLineInfo.LinePosition);
}
if(r.MoveToFirstAttribute())
{

{
XAttribute XAttribute=new XAttribute(namespaceCache2.Get((r.Prefix.Length==0)?string.Empty:r.NamespaceURI.GetName(r.LocalName),r.Value);
if(xmlLineInfo!=null&xmlLineInfo.HasLineInfo())
{
xAttribute.SetLineInfo(xmlLineInfo.LineNumber,xmlLineInfo.LinePosition);
}
xElement.AppendAttributeSkipNotify(xAttribute);
}
while(r.MoveToNextAttribute());
r、 MoveToElement();
}
xContainer.AddNodeSkipNotify(xElement);
如果(r.IsEmptyElement)
{
goto IL_30A;
}
xContainer=xElement;
如果(文本!=null)
{
text=baseURI;
goto IL_30A;
}
goto IL_30A;
}
案例XmlNodeType.Text:
大小写XmlNodeType.Whitespace:
大小写XmlNodeType.SignificantWhitespace:
if((text!=null&text!=baseURI)| |(xmlLineInfo!=null&xmlLineInfo.HasLineInfo())
{
xNode=新的XText(r.Value);
goto IL_30A;
}
xContainer.AddStringSkipNotify(r.Value);
goto IL_30A;
案例XmlNodeType.CDATA:
xNode=新的XCData(r.值);
goto IL_30A;
案例XmlNodeType.EntityReference:
if(!r.CanResolveEntity)
{
后藤25号楼;
}
r、 ResolveEntity();
goto IL_30A;
案例XmlNodeType.ProcessingInstruction:
xNode=新的XProcessingInstruction(r.Name,r.Value);
goto IL_30A;
案例XmlNodeType.Comment:
xNode=新的XComment(r值);
goto IL_30A;
案例XmlNodeType.DocumentType:
xNode=newxdocumenttype(r.LocalName、r.GetAttribute(“PUBLIC”)、r.GetAttribute(“SYSTEM”)、r.Value、r.DtdInfo);
goto IL_30A;
案例XmlNodeType.EndElement:
{
if(xContainer.content==null)
{
xContainer.content=string.Empty;
}
XElement xElement2=xContainer作为XElement;
if(xElement2!=null&xmlLineInfo!=null&xmlLineInfo.HasLineInfo())
{
xElement2.SetEndElementLineInfo(xmlLineInfo.LineNumber,xmlLineInfo.LinePosition);
}
如果(xContainer==此)
{
回来
}
if(text!=null&xContainer.HasBaseUri)
{
text=xContainer.parent.BaseUri;
}
xContainer=xContainer.parent;
goto IL_30A;
}
案例XmlNodeType.EndEntity:
goto IL_30A;
}
打破
IL_30A:
if(xNode!=null)
{
if(text!=null&text!=baseURI)
{
xNode.SetBaseUri(baseURI);
}
if(xmlLineInfo!=null&xmlLineInfo.HasLineInfo())
{
xNode.SetLineInfo(xmlLineInfo.LineNumber,xmlLineInfo.LinePosition);
}
xContainer.AddNodeSkipNotify(xNode);
xNode=null;
}
如果(!r.Read())
{
回来
}
}
goto IL_2E1;
第25区:
抛出新的InvalidOperationException(Res.GetString(“InvalidOperation\u UnsolvedEntityReference”);
IL_2E1:
抛出新的InvalidOperationException(Res.GetString(“InvalidOperation_UnexpectedNodeType”),新对象[]
{
r、 节点类型
}));
}

发表评论