假设我有一个导出(序列化)功能,可执行以下操作
public void ExportToXML()
{
var DCS = new DataContractSerializer(typeof(Entry));
var XWriter = XmlWriter.Create(@"C:\Temp\Export.xml");
XWriter.WriteStartDocument();
XWriter.WriteStartElement("Entries");
Entries.ForEach(e =>
{
DCS.WriteStartObject(XWriter, e);
DCS.WriteObjectContent(XWriter, e);
DCS.WriteEndObject(XWriter);
});
XWriter.WriteEndElement();
XWriter.WriteEndDocument();
XWriter.Close();
}
导出一个看起来像
的XML文件<Entries>
<Entry>{Some Data}</Entry>
<Entry>{Some Data}</Entry>
<Entry>{Some Data}</Entry>
<Entry>{Some Data}</Entry>
</Entries>
对于Import方法,我想一次反序列化每个
<Entry>{Some Data}</Entry>,以便我可以应用转换
Func<Entry,Entry>
如果
Func<Entry,bool>
谓词是真的
这就是我想出来的
public void ImportFromXML(string FileName, Func<Entry,Entry> Transform, Func<Entry,bool> DoTransform)
{
var DCS = new DataContractSerializer(typeof(Entry));
var ImportedEntries = new List<Entry>();
foreach (var EntryElement in XDocument.Load(FileName).Root.Elements().Where(xe => xe.Name.LocalName == "Entry"))
{
var XMLEntry = (Entry)DCS.ReadObject(EntryElement.CreateReader());
ImportedEntries.Add(DoTransform(XMLEntry) ? Transform(XMLEntry) : XMLEntry);
}
entries = ImportedEntries.ToDictionary(e => e.KeyName + "\\" + e.ValueName);
}
哪个有效,但我想知道是否有一种方法可以使用单个XmlReader一次性执行此操作,而不是生成每个XElement的XMLReader。
我试图扭转导出方法的逻辑
public void ImportFromXML(string FileName, Func<Entry,Entry> Transform, Func<Entry,bool> DoTransform)
{
var DCS = new DataContractSerializer(typeof(Entry));
var ImportedEntries = new List<Entry>();
var XReader = XmlReader.Create(@"C:\Temp\Export.xml");
XReader.ReadStartElement("Entries");
while (!{WHAT Exit Condition?})
{
var XMLEntry = (Entry)DCS.ReadObject(XReader());
ImportedEntries.Add(DoTransform(XMLEntry) ? Transform(XMLEntry) : XMLEntry);
}
XReader.Close();
entries = ImportedEntries.ToDictionary(e => e.KeyName + "\\" + e.ValueName);
}
但是我不确定要投入什么
{WHAT Exit Condition?}显然我无法使用
!XReader.EOF因为读到文件末尾将导致它尝试反序列化结束&lt; / Entries&gt;标记为条目。
这些方法所属的类将作为我们的SCCM操作系统部署任务序列的一部分使用,这意味着它们可以被多个同时运行的任务序列使用,这些任务序列通过网络查询源XML文件。所以我有点担心更好的表现。
我是在追逐我的尾巴尝试使用单个XmlReader执行此操作,还是将LINQ to XML与单独的XmlReader结合使用是最佳选择?
答案 0 :(得分:1)
XML文件可以使用缩进编写,无需缩进。在前一种情况下,以下代码可以正常工作:
var settings = new XmlWriterSettings { Indent = true };
var DCS = new DataContractSerializer(typeof(Entry));
using (var writer = XmlWriter.Create(fileName, settings)) // with indentation
{
writer.WriteStartDocument();
writer.WriteStartElement("Entries");
foreach (var entry in Entries)
{
DCS.WriteObject(writer, entry);
}
}
using (var reader = XmlReader.Create(fileName))
{
while (reader.ReadToFollowing("Entry"))
{
var xmlEntry = (Entry)DCS.ReadObject(reader);
// ...
}
}
在这种情况下,ReadToFollowing
方法首先读取空格,然后前进到下一个Entry
节点。但是在没有缩进的情况下,该方法会跳过一个Entry
节点。
在后一种情况下,我们可以使用以下代码:
using (var writer = XmlWriter.Create(fileName)) // without indentation
// ...
using (var reader = XmlReader.Create(fileName))
{
while (reader.LocalName == "Entry" || reader.ReadToFollowing("Entry"))
{
var xmlEntry = (Entry)DCS.ReadObject(reader);
// ...
}
}
此外,此代码在两种情况下都能正常工作。
答案 1 :(得分:0)
如果您的转换足够规则,那么进行XSLT转换并将其应用于源文档将是我采取的方法。您可以创建xml或非xml输出。如果您从未使用它,那有点奇怪......但是您编写了xsl:apply-template
元素来选择输入,然后嵌套 Application.Run(loginForm);
if (loginForm.IsLoggedIn == true)
{
ERS_FDData.ERSUser user = loginForm.user;
loginForm.Close();
Application.Run(new frmMain(loginForm.user));
}
else
Application.Exit();
元素来描述如何转换所选部分。为您的问题定制的声音。
一个很好的例子,在相关的问题中可以找到MPI_MAXLOC
,以及使用XSLT here的50,000英尺概述。