【问题标题】:Where is my XDeclaration?我的 XDeclaration 在哪里?
【发布时间】:2011-06-07 18:26:28
【问题描述】:

由于某种原因,以下代码生成的 XML 不包含声明:

        XDocument xDocument = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),
            new XElement("project",
                new XAttribute("number", project.ProjectNumber),
                new XElement("store",
                    new XAttribute("number", project.StoreNumber)
                ),

                // User Element
                new XElement("user", 
                    new XAttribute("owner-id", project.OwnerID ?? 0),
                    new XElement("email", new XCData(project.OwnerEmail ?? "")),
                    new XElement("project-name", new XCData(project.ProjectName ?? ""))
                ),

                // Nested Project Element
                new XElement("nested-project", 
                    new XAttribute("version", new Version(1, 0)),
                    new XElement("project", 
                        new XAttribute("version", new Version(1, 0)),
                        xProjectItems = new XElement("project-items")
                    ),
                    new XElement("price-per-part", project.PricePerPart),
                    new XElement("sheet-quantity", project.SheetQuantity),
                    new XElement("edge-length", project.EdgeLength),
                    new XElement("price", project.Price),
                    new XElement("status", project.Status),
                    xMaterialItems = new XElement("alternative-material-items"),
                    xProductItems = new XElement("project-product-items")
                )
            )
        );

        String strXML = xDocument.ToString();

它之前已经产生了一个声明。我错过了什么明显的东西吗?

谢谢。

【问题讨论】:

    标签: c# .net xml linq-to-xml


    【解决方案1】:

    当您使用XDocument.Save methods 之一时,XDeclaration 将可用。例如:

    var doc = new XDocument (
                new XDeclaration ("1.0", "utf-8", "yes"),
                new XElement ("test", "data")
            );
    
    string path = Path.Combine(Path.GetTempPath(), "temp.xml");
    doc.Save(path);
    Console.WriteLine(File.ReadAllText(path));
    

    您也可以使用这种方法:

    var sw = new StringWriter();
    doc.Save(sw);
    string result = sw.GetStringBuilder().ToString();
    Console.WriteLine(result);
    

    编辑:请注意,某些方法会将 utf-8 名称转换为 utf-16。如果你想强制它为 utf-8,你将不得不使用这种不同的方法:

    using (var mem = new MemoryStream())  
    using (var writer = new XmlTextWriter(mem, System.Text.Encoding.UTF8))
    {
        writer.Formatting = Formatting.Indented;
        doc.WriteTo(writer);
        writer.Flush();
        mem.Flush();
        mem.Seek(0, SeekOrigin.Begin);
        using (var reader = new StreamReader(mem))
        {
            var xml = reader.ReadToEnd();
            Console.WriteLine(xml);
        }
    }
    

    【讨论】:

    • 那是蹩脚的。不是你的解决方案(这很酷——我没有意识到你可以用StringWriter 做到这一点)。微软会这样做是蹩脚的。我没有将此 XML 保存到文件中,而是将其传递到流中。 “XDocument”和“XElement”有什么区别。我的意思是它们相似是好事,但应该有一些区别。如果有人不想要字符串中的声明,那么你可以这样做:xMyDocument.Root.ToString();
    • @Jordan 我想基本原理是 XDocument 代表整个文档,而 XElement 是 XML 的片段。尽管如此,它们还是非常相似的。
    • 哦,我知道它们通常有什么不同,但在 LINQ to XML 中,XDocument 似乎只不过是一个无法包含的XElement
    【解决方案2】:

    documentation 没有明确声明xDocument.ToString() 将输出 XML 声明,它只是说:“返回此节点的缩进 XML。”。

    在我的测试中,我发现以下方法会输出声明:

    Declaration 属性上使用ToString

    string strXML = string.Concat(xDocument.Declaration.ToString(), "\r\n",
                                  xDocument.ToString());
    

    或使用Save 方法:

    string strXml;
    using(var ms = new MemoryStream())
    {
        xDocument.Save(ms);
        ms.Position = 0;
        using(var sr = new StreamReader(ms))
        {
            strXml = sr.ReadToEnd();
        }
    }
    

    【讨论】:

    • 注意:我认为@Ahmad Mageed 使用StringWriter 的方法是可行的方法。相同的想法,但比我的 Save 方法短。
    • +1 表示努力。我想当需要强制编码时,有一种更长的方法,如我的编辑所示。
    【解决方案3】:

    我的回答(灵感来自the answer by @rsbarro):

    string xml = xDocument.Declaration.ToString() +
        xDocument.ToString();
    

    - 或 -

    string xml = xDocument.Declaration.ToString() +
        xDocument.ToString(SaveOptions.DisableFormatting);
    

    关于为什么我认为在这种情况下使用+ 运算符是合适的,请参阅this answer 问题What's the best string concatenation method using C#?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多