【问题标题】:XDocument.ToString() drops XML Encoding TagXDocument.ToString() 丢弃 XML 编码标记
【发布时间】:2009-08-04 17:50:14
【问题描述】:

有没有办法在toString()函数中获取xml编码?

示例:

xml.Save("myfile.xml");

导致

<?xml version="1.0" encoding="utf-8"?>
<Cooperations>
  <Cooperation>
    <CooperationId>xxx</CooperationId>
    <CooperationName>Allianz Konzern</CooperationName>
    <LogicalCustomers>

但是

tb_output.Text = xml.toString();

导致这样的输出

<Cooperations>
  <Cooperation>
    <CooperationId>xxx</CooperationId>
    <CooperationName>Allianz Konzern</CooperationName>
    <LogicalCustomers>
    ...

【问题讨论】:

    标签: c# linq-to-xml


    【解决方案1】:

    要么明确写出声明,要么使用StringWriter 并调用Save()

    using System;
    using System.IO;
    using System.Text;
    using System.Xml.Linq;
    
    class Test
    {
        static void Main()
        {
            string xml = @"<?xml version='1.0' encoding='utf-8'?>
    <Cooperations>
      <Cooperation />
    </Cooperations>";
    
            XDocument doc = XDocument.Parse(xml);
            StringBuilder builder = new StringBuilder();
            using (TextWriter writer = new StringWriter(builder))
            {
                doc.Save(writer);
            }
            Console.WriteLine(builder);
        }
    }
    

    您可以轻松地将其添加为扩展方法:

    public static string ToStringWithDeclaration(this XDocument doc)
    {
        if (doc == null)
        {
            throw new ArgumentNullException("doc");
        }
        StringBuilder builder = new StringBuilder();
        using (TextWriter writer = new StringWriter(builder))
        {
            doc.Save(writer);
        }
        return builder.ToString();
    }
    

    这样做的好处是,如果没有声明,它就不会爆炸:)

    那么你可以使用:

    string x = doc.ToStringWithDeclaration();
    

    请注意,这将使用 utf-16 作为编码,因为这是 StringWriter 中的隐式编码。您可以通过创建StringWriter 的子类来影响自己,例如to always use UTF-8.

    【讨论】:

    • 这有一个小问题,即 XDocument 声明中的编码在进行保存时被忽略并替换为 StringWriter 的编码,这可能是也可能不是您想要的
    • 然后你将扩展​​方法与:Utf8StringWriter from stackoverflow.com/a/1564727/75963 ;)
    • 发现使用上面的扩展方法更容易,但返回以下内容... return doc.Declaration + doc.ToString();如果声明为空,它只会产生一个空字符串。
    • 奇怪,但我现在无法正常工作 (.net fiddle) - 它总是使用“utf-16”编码。我查看了XDocument.Save(TextWriter) 实现内部,它只是忽略了声明的编码,而不是XDocument.Save(String)XDocument.Save(Stream) 实现。我想知道为什么...
    • @IlyaLuzyanin:是的,当您传入StringWriter 时,它将使用“utf-16”作为编码,除非您使用覆盖Encoding 属性的编码。我对此有另一个答案。我以为你是说它完全放弃了“编码”......
    【解决方案2】:

    Declaration 属性将包含 XML 声明。要获取内容加声明,您可以执行以下操作:

    tb_output.Text = xml.Declaration.ToString() + xml.ToString()
    

    【讨论】:

    • 似乎如果您不在 xdocument 中使用 new XDeclaration("1.0", "utf-8", "yes") 这会产生错误,因为 xml.Declaration 为空。但是 xml.save 似乎可以自动检测到正确的编码。
    • 或者,tb_output.Text = @"&lt;?xml version=""1.0"" encoding=""utf-8"" ?&gt;" + xml;
    • ... = $"{xdoc.Declaration}{Environment.NewLine}{xdoc}";
    【解决方案3】:

    使用这个:

    output.Text = String.Concat(xml.Declaration.ToString() , xml.ToString())
    

    【讨论】:

    • 如果不创建新的 XDeclaration("1.0", "utf-8", "yes") 并添加到 XDocument 或其他对象中,xml.Declaration.ToString() 将抛出空异常。跨度>
    • 这样更安全,因为 Concat 不关心空字符串: output.Text = String.Concat(xml.Declaration , xml)
    【解决方案4】:

    我喜欢这个

            string distributorInfo = string.Empty;
    
            XDocument distributors = new XDocument();
    
         //below is important else distributors.Declaration.ToString() throws null exception
            distributors.Declaration = new XDeclaration("1.0", "utf-8", "yes"); 
    
            XElement rootElement = new XElement("Distributors");
            XElement distributor = null;
            XAttribute id = null;
    
            distributor = new XElement("Distributor");
            id = new XAttribute("Id", "12345678");
            distributor.Add(id);
            rootElement.Add(distributor);
    
            distributor = new XElement("Distributor");
            id = new XAttribute("Id", "22222222");
    
            distributor.Add(id);
    
            rootElement.Add(distributor);         
    
            distributors.Add(rootElement);
    
            distributorInfo = String.Concat(distributors.Declaration.ToString(), distributors.ToString());
    

    请看下面我在distributorInfo中得到的信息

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <Distributors>
      <Distributor Id="12345678" />
      <Distributor Id="22222222" />
      <Distributor Id="11111111" />
    </Distributors>
    

    【讨论】:

    • 很好的例子。一些注意事项:1) 使用 new XDeclaration("1.0", "utf-8") 而不是 new XDeclaration("1.0", "utf-8", "yes"),2) 在最后一行插入新行:distributors。 Declaration.ToString() + Environment.NewLine +distributors.ToString()
    【解决方案5】:

    与其他 +1 答案类似,但有关声明的更多细节,以及更准确的串联。

    &lt;xml /&gt; 声明应该在格式化的 XML 中单独一行,所以我确保我们添加了换行符。 注意:使用Environment.Newline,因此它将生成特定于平台的换行符

    // Parse xml declaration menthod
    XDocument document1 =
      XDocument.Parse(@"<?xml version=""1.0"" encoding=""iso-8859-1""?><rss version=""2.0""></rss>");
    string result1 =
      document1.Declaration.ToString() +
      Environment.NewLine +
      document1.ToString() ;
    
    // Declare xml declaration method
    XDocument document2 = 
      XDocument.Parse(@"<rss version=""2.0""></rss>");
    document2.Declaration =
      new XDeclaration("1.0", "iso-8859-1", null);
    string result2 =
      document2.Declaration.ToString() +
      Environment.NewLine +
      document2.ToString() ;
    

    两个结果都产生:

    <?xml version="1.0" encoding="iso-8859-1"?>
    <rss version="2.0"></rss>
    

    【讨论】:

      【解决方案6】:

      其中一些答案解决了发帖人的要求,但似乎过于复杂。这是一个简单的扩展方法,它避免了需要单独的编写器、处理丢失的声明并支持标准的 ToString SaveOptions 参数。

      public static string ToXmlString(this XDocument xdoc, SaveOptions options = SaveOptions.None)
      {
          var newLine =  (options & SaveOptions.DisableFormatting) == SaveOptions.DisableFormatting ? "" : Environment.NewLine;
          return xdoc.Declaration == null ? xdoc.ToString(options) : xdoc.Declaration + newLine + xdoc.ToString(options);
      }
      

      要使用扩展,只需将xml.ToString() 替换为xml.ToXmlString()

      【讨论】:

        【解决方案7】:

        您也可以使用 XmlWriter 并调用

        Writer.WriteDocType() 
        

        方法。

        【讨论】:

          【解决方案8】:
          string uploadCode = "UploadCode";
          string LabName = "LabName";
          XElement root = new XElement("TestLabs");
          foreach (var item in returnList)
          {  
                 root.Add(new XElement("TestLab",
                          new XElement(uploadCode, item.UploadCode),
                          new XElement(LabName, item.LabName)
                                      )
                         );
          }
          
          XDocument returnXML = new XDocument(new XDeclaration("1.0", "UTF-8","yes"),
                       root);
          
          string returnVal;
          using (var sw = new MemoryStream())
          {
                 using (var strw = new StreamWriter(sw, System.Text.UTF8Encoding.UTF8))
                 {
                        returnXML.Save(strw);
                        returnVal = System.Text.UTF8Encoding.UTF8.GetString(sw.ToArray());
                 }
          }
          
          // ReturnVal has the string with XML data with XML declaration tag
          

          【讨论】:

            【解决方案9】:

            获取包含 Xml 声明的扩展方法,在此处使用字符串插值,并选择在 xml 声明后添加新行,因为这是我猜的标准。

            public static class XDocumentExtensions {
                    
            public static string ToStringIncludeXmlDeclaration(this XDocument doc){
                           return $"({((doc.Declaration != null ? doc.Declaration.ToString() + 
                 Environment.NewLine : string.Empty) + doc.ToString())}";
                }  
              }
            }
            

            用法:

            tb_output.Text = xml.ToStringIncludeXmlDeclaration();
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-04-12
              • 2017-03-07
              • 2022-07-25
              • 1970-01-01
              • 2019-01-15
              • 1970-01-01
              • 1970-01-01
              • 2016-11-20
              相关资源
              最近更新 更多