在 Document 状态下使用 Linq: Token EndDocument 写入 XML 会导致无效的 XML 文档

Writing XML with Linq: Token EndDocument in state Document would result in an invalid XML document

[看起来比实际多]

我正在尝试编写一个小的 C# 程序,通过 IMAP 下载邮件帐户的邮件。我有一个包含电子邮件对象的列表和一个方法,该方法应该 return 一个用列表中的数据填充的有效 XDocument。 XML 应该看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<Folder ID="0" name="INBOX">
    <Mail UID="328" fromAddress="serious.business@server.com" fromDisplayName="Business guy" toAddress="me@server.com" toDisplayName="David Onter">
        <Priority>High</Priority>
        <Subject>Important info!</Subject>
        <Content>The Content goes in here.</Content>
        <AttachmentPath>/Attachments/important_document.pdf</AttachmentPath>
    </Mail>
    <Mail UID="329" fromAddress="coolkid@server.com" fromDisplayName="The cool kid" toAddress="me@server.com" toDisplayName="David Onter">
        <Priority>Normal</Priority>
        <Subject>Waaazuuuuup</Subject>
        <Content>Stay fly and snazzy</Content>
        <AttachmentPath></AttachmentPath>
    </Mail>
</Folder>
<Folder ID="1" name="Archive">
    <Mail UID="420" fromAddress="dude@server.com" fromDisplayName="Classmate8" toAddress="me@server.com" toDisplayName="David Onter">
        <Priority>Normal</Priority>
        <Subject>Maths homework</Subject>
        <Content>What was maths hw?</Content>
        <AttachmentPath></AttachmentPath>
    </Mail>
</Folder>

这是它抛出的错误:

System.InvalidOperationException: Token EndDocument in state Document would result in an invalid XML document.
at System.Xml.XmlWellFormedWriter.ThrowInvalidStateTransition(Token token, State currentState)
at System.Xml.XmlWellFormedWriter.AdvanceState(Token token)
at System.Xml.XmlWellFormedWriter.WriteEndDocument()
at System.Xml.Linq.XDocument.WriteTo(XmlWriter writer)
at System.Xml.Linq.XDocument.Save(String fileName, SaveOptions options)
at System.Xml.Linq.XDocument.Save(String fileName)
at DownTheMail.Program.Main(String[] args)

// Export to xml
XDocument xmlDoc = MailToXML(emailList);
xmlDoc.Save(@"C:\Users\David\Documents\file.xml");

这是实际的方法:

private static XDocument MailToXML(List<Email> emailList) {
    XDocument xmlDoc = new XDocument(new XDeclaration("1.0", "UTF-16", "yes"));
    // Compiler food, will be overwritten.
    XElement folder = new XElement("Folder");

    for(int i=0; i<emailList.Count; i++) {
        if(i!=0&&emailList[i-1].FolderId==emailList[i].FolderId) {
            // Write Mail and add it to the current folder
            folder.Add(new XElement("Mail", new XAttribute("UID", emailList[i].Uid),
                                            new XAttribute("fromAddress", emailList[i].FromAddress),
                                            new XAttribute("fromDisplayName", emailList[i].FromDisplayName),
                                            new XAttribute("ToAddresses", emailList[i].ToAddresses),
                                            new XAttribute("ToDisplayNames", emailList[i].ToDisplayNames),
                                                new XElement("Importance", emailList[i].Importance),
                                                new XElement("Subject", emailList[i].Subject),
                                                new XElement("BodyText", emailList[i].BodyText),
                                                new XElement("AttachmentPath", emailList[i].AttachmentPath)));
        } else {
            if(i!=0) {
                // Add current, finished folder to the document
                xmlDoc.Add(folder);
            }
            // Create new folder
            folder = new XElement("Folder", new XAttribute("id", emailList[i].FolderId),
                                            new XAttribute("name", emailList[i].FolderName));

            // Write Mail and add it to the newly created folder as the first element
            folder.Add(new XElement("Mail", new XAttribute("UID", emailList[i].Uid),
                                            new XAttribute("fromAddress", emailList[i].FromAddress),
                                            new XAttribute("fromDisplayName", emailList[i].FromDisplayName),
                                            new XAttribute("ToAddresses", emailList[i].ToAddresses),
                                            new XAttribute("ToDisplayNames", emailList[i].ToDisplayNames),
                                                new XElement("Importance", emailList[i].Importance),
                                                new XElement("Subject", emailList[i].Subject),
                                                new XElement("BodyText", emailList[i].BodyText),
                                                new XElement("AttachmentPath", emailList[i].AttachmentPath)));
        }
    }

    return xmlDoc;
}

结果XML肯定是无效的,因为xml只允许一个根元素。实际上,XDocument class 公开了类型为 XElement 的 "Root" 属性。您可以将 "folder" 添加到此 "Root" 元素而不是直接添加 XDocument。

您也可以使用简单的 xml 字符串而不是 XDeclaration 来初始化 XDocument。

您的 XML 中缺少 Root 元素。您提供的 XML 无效。例如向 XML 后面添加根元素会使它 有效。 XML 文档必须包含一个根元素,它是所有其他元素的父元素:来自 wikipedia.

Each XML document has exactly one single root element. It encloses all the other elements and is therefore the sole parent element to all the other elements. ROOT elements are also called PARENT elements.

<?xml version="1.0" encoding="UTF-8"?> <root> <Folder ID="0" name="INBOX"> <Mail UID="328" fromAddress="serious.business@server.com" fromDisplayName="Business guy" toAddress="me@server.com" toDisplayName="David Onter"> <Priority>High</Priority> <Subject>Important info!</Subject> <Content>The Content goes in here.</Content> <AttachmentPath>/Attachments/important_document.pdf</AttachmentPath> </Mail> <Mail UID="329" fromAddress="coolkid@server.com" fromDisplayName="The cool kid" toAddress="me@server.com" toDisplayName="David Onter"> <Priority>Normal</Priority> <Subject>Waaazuuuuup</Subject> <Content>Stay fly and snazzy</Content> <AttachmentPath></AttachmentPath> </Mail> </Folder> <Folder ID="1" name="Archive"> <Mail UID="420" fromAddress="dude@server.com" fromDisplayName="Classmate8" toAddress="me@server.com" toDisplayName="David Onter"> <Priority>Normal</Priority> <Subject>Maths homework</Subject> <Content>What was maths hw?</Content> <AttachmentPath></AttachmentPath> </Mail> </Folder> </root>