使用c#从xml片段生成格式良好的xml
本文关键字:xml 格式 片段 使用 | 更新日期: 2023-09-27 17:49:45
我正在从循环中制定xmlnodes。它的作用是
var settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
foreach (Person human in bar)
{
var serializer = new XmlSerializer(typeof(Person));
using (var stream = new FileStream(filepath, FileMode.Append))
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, human, ns);
}
}
当循环完成时,生成xml片段输出xml如下所示
<Person>
<Name>mar8a</Name>
<Age>11</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person>
<Person>
<Name>mar1a</Name>
<Age>1</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person>
<Person>
<Name>mar2a</Name>
<Age>11</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person>
<Person>
<Name>mar3a</Name>
<Age>1</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person><Person>
<Name>mar4a</Name>
<Age>11</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person>
<Person>
<Name>mar5a</Name>
<Age>11</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person>
<Person>
<Name>mar6a</Name>
<Age>11</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person>
<Person>
<Name>mar7a</Name>
<Age>11</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person>
<Person>
<Name>mar8a</Name>
<Age>11</Age>
<Sex>MALE</Sex>
<Address>TOP 92 BOTTOM</Address>
<SingleYn>false</SingleYn>
</Person>
我正在运行的问题是如何修改它并使其成为一个格式良好的XML,在循环结束时具有根节点和声明。
我尝试了下面的概念,但是没有成功,因为它限制了我不能在写入器上写入根元素。
StringBuilder output = new StringBuilder();
XmlReaderSettings ws = new XmlReaderSettings();
ws.ConformanceLevel = ConformanceLevel.Fragment;
String xmlString =
@"<Item>test with a child element stuff</Item>
<Item>test with a child element stuff</Item>";
// Create an XmlReader
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString), ws))
{
XmlWriterSettings ws2 = new XmlWriterSettings();
ws2.Indent = true;
using (XmlWriter writer = XmlWriter.Create(output, ws2))
{
writer.WriteStartDocument();
// Parse the file and display each of the nodes.
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
writer.WriteStartElement(reader.Name);
break;
case XmlNodeType.Text:
writer.WriteString(reader.Value);
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
writer.WriteProcessingInstruction(reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
writer.WriteComment(reader.Value);
break;
case XmlNodeType.EndElement:
writer.WriteFullEndElement();
break;
}
}
writer.WriteEndDocument();
}
}
更新! !
下面是序列化列表的代码我的序列化器
的实现 public static async Task WriteXMLAsync<T>(this List<T> listRows, T entity, VMEXPORT[] arrVmExport, string filePath)
where T : class
{
XmlWriterSettings Xmlsettings = new XmlWriterSettings();
Xmlsettings.Indent = true;
Xmlsettings.OmitXmlDeclaration = false;
Xmlsettings.NewLineOnAttributes = true;
Xmlsettings.Async = true;
Xmlsettings.Encoding = Encoding.UTF8;
Xmlsettings.CheckCharacters = false;
XmlAttributeOverrides Xmloverrides = new XmlAttributeOverrides();
XmlAttributes Xmlattribs = new XmlAttributes();
Xmlattribs.XmlIgnore = true;
Xmlattribs.XmlElements.Add(new XmlElementAttribute("SfiObjectState"));
Xmloverrides.Add(typeof(T), "SfiObjectState", Xmlattribs);
if (!File.Exists(filePath))
{
using (var fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 4096, true))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<T>), Xmloverrides);
using (XmlWriter xmlWriter = XmlWriter.Create(fileStream, Xmlsettings))
{
serializer.Serialize(xmlWriter, listRows);
await xmlWriter.FlushAsync();
}
}
}
else
{
using (var fileStream = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.None, 4096, true))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<T>), Xmloverrides);
using (XmlWriter xmlWriter = XmlWriter.Create(fileStream, Xmlsettings))
{
serializer.Serialize(xmlWriter, listRows);
await xmlWriter.FlushAsync();
}
}
}
}
在上面的方法上迭代实现take和skip
public async Task WriteXmlDataAsync<TEntity>(IQueryable<TEntity> listToWrite, [DataSourceRequest]DataSourceRequest dataRequest,
int countno, VMEXPORT[] vmExportarr, CancellationToken token,
TEntity entity, string csvFileNametx, string XmlFilePathtx)
where TEntity : class
{
dataRequest.GroupingToSorting();
int datapageno = (countno / GeneralConst.L_MAX_EXPORT_REC) + 1;
for (int ctrno = 1; ctrno <= datapageno; )
{
if (token.IsCancellationRequested)
{
RemoveTask(csvFileNametx);
token.ThrowIfCancellationRequested();
}
dataRequest.Page = ctrno;
dataRequest.PageSize = GeneralConst.L_MAX_EXPORT_REC;
var dataSourceResult = listToWrite.ToDataSourceResult(dataRequest);
await dataSourceResult.Data.Cast<TEntity>().ToList().WriteXMLAsync(entity, vmExportarr, XmlFilePathtx);
ctrno = ctrno + 1;
int percentageno = (ctrno * 100) / datapageno;
if (percentageno > 100) percentageno = 100;
UpdateTask(csvFileNametx, percentageno);
}
}
选项1
在XML文件写好之后,您可以像这样做一些快速而肮脏的事情:
public static void AddOuterElement(string fileName, string elementName)
{
var startElement = string.Format(@"<{0}>", elementName);
var endElement = string.Format(@"</{0}>", elementName);
var tmpName = Path.GetTempFileName();
try
{
using (var writer = new StreamWriter(tmpName, false, Encoding.UTF8))
{
writer.WriteLine(startElement);
foreach (var line in File.ReadLines(fileName)) // Reads lines incrementally rather than all at once.
writer.WriteLine(line);
writer.WriteLine(endElement);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
try
{
System.IO.File.Delete(tmpName);
}
catch (Exception)
{
}
throw;
}
System.IO.File.Delete(fileName);
System.IO.File.Move(tmpName, fileName);
}
这需要编写两次XML文件。
选项2
假设您有一些方法可以以块形式返回Person
类的列表,例如使用以下签名:
IEnumerable<IEnumerable<Person>> GetPeopleInChunks()
{
// Query the database in chunks of 200 and yield return each list.
}
那么你可以使用下面的类来序列化数据库中所有的人,而不必一次将他们全部加载到内存中:
// Proxy class for any enumerable with the requisite `Add` methods.
public class EnumerableProxy<T> : IEnumerable<T>
{
[XmlIgnore]
public IEnumerable<T> BaseEnumerable { get; set; }
public void Add(T obj)
{
throw new NotImplementedException();
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
if (BaseEnumerable == null)
return Enumerable.Empty<T>().GetEnumerator();
return BaseEnumerable.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
[XmlRoot("People")]
public class People
{
[XmlIgnore]
public IEnumerable<Person> Results { get; set; }
[XmlElement("Person")]
public EnumerableProxy<Person> ResultsProxy
{
get
{
return new EnumerableProxy<Person> { BaseEnumerable = Results };
}
set
{
throw new NotImplementedException();
}
}
}
然后:
public void WriteXml(string fileName)
{
var people = new People { Results = GetPeopleInChunks().SelectMany(chunk => chunk) };
using (var writer = XmlWriter.Create(fileName))
{
new XmlSerializer(typeof(People)).Serialize(writer, people);
}
}
尝试如下内容。您还需要在根级别只有一层标记。
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlStr);
XmlDeclaration xDeclare = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.InsertBefore(xDeclare, doc.FirstChild);
//or
string xml1 ="<Root>" + "Your XML" + "</Root>";
//or
string xml2 = "<?xml version='"1.0'" encoding='"UTF-8'"?><Root>" + "Your XML" + "</Root>";
假设所有Person节点都在某种描述的字符串中,那么将其转换为文档的简单方法如下:
XmlDocument oXmlDocument = new XmlDocument();
oXmlDocument.AppendChild(oXmlDocument.CreateXmlDeclaration("1.0", "UTF-8", ""));
string sFileContents = "XML Fragments In Here";
XmlNode oRootXmlNode = oXmlDocument.CreateElement("Root");
oRootXmlNode.InnerXml = sFileContents;
oXmlDocument.AppendChild(oRootXmlNode);
oXmlDocument.Save("XMLFileName.xml");
如果片段最终非常大,这可能不是一个好主意