不带<;的.NET XML序列化;?xml>;文本声明

不带<;的.NET XML序列化;?xml>;文本声明,.net,xml-serialization,.net-2.0,.net,Xml Serialization,.net 2.0,我正在尝试生成如下XML: <?xml version="1.0"?> <!DOCTYPE APIRequest SYSTEM "https://url"> <APIRequest> <Head> <Key>123</Key> </Head> <ObjectClass> <Field>Value</Field </ObjectClass>

我正在尝试生成如下XML:

<?xml version="1.0"?>
<!DOCTYPE APIRequest SYSTEM
"https://url">
<APIRequest>
  <Head>
      <Key>123</Key>
  </Head>
  <ObjectClass>
    <Field>Value</Field
  </ObjectClass>
</APIRequest>
[XmlRoot("ObjectClass")]
public class ObjectClass
{
    [XmlElement("Field")]
    public string Field { get; set; }
}
<?xml version="1.0"?>
<!DOCTYPE APIRequest SYSTEM
"https://url">
<APIRequest>
  <Head>
      <Key>123</Key>
  </Head>
  <?xml version="1.0" encoding="utf-16"?>
  <ObjectClass>
    <Field>Value</Field>
  </ObjectClass>
</APIRequest>
我的直觉是,当我序列化时,我会这样做:

ObjectClass inst = new ObjectClass();
XmlSerializer serializer = new XmlSerializer(inst.GetType(), "");

StringWriter w = new StringWriter();
w.WriteLine(@"<?xml version=""1.0""?>");
w.WriteLine("<!DOCTYPE APIRequest SYSTEM");
w.WriteLine(@"""https://url"">");
w.WriteLine("<APIRequest>");
w.WriteLine("<Head>");
w.WriteLine(@"<Field>Value</Field>");
w.WriteLine(@"</Head>");

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", ""); 
serializer.Serialize(w, inst, ns);

w.WriteLine("</APIRequest>");
ObjectClass inst=new ObjectClass();
XmlSerializer serializer=新的XmlSerializer(inst.GetType(),“”);
StringWriter w=新的StringWriter();
w、 书写线(@“);
w、 书写线(“”);
w、 书写线(“”);
w、 书写线(“”);
w、 写线(@“值”);
w、 书写线(@“);
XmlSerializerNamespaces ns=新的XmlSerializerNamespaces();
加上(“,”);
序列化器。序列化(w,inst,ns);
w、 书写线(“”);
但是,这会生成如下XML:

<?xml version="1.0"?>
<!DOCTYPE APIRequest SYSTEM
"https://url">
<APIRequest>
  <Head>
      <Key>123</Key>
  </Head>
  <ObjectClass>
    <Field>Value</Field
  </ObjectClass>
</APIRequest>
[XmlRoot("ObjectClass")]
public class ObjectClass
{
    [XmlElement("Field")]
    public string Field { get; set; }
}
<?xml version="1.0"?>
<!DOCTYPE APIRequest SYSTEM
"https://url">
<APIRequest>
  <Head>
      <Key>123</Key>
  </Head>
  <?xml version="1.0" encoding="utf-16"?>
  <ObjectClass>
    <Field>Value</Field>
  </ObjectClass>
</APIRequest>

123
价值

i、 e.serialize语句自动添加一个从不使用字符串连接构建xml。这是邪恶的

输出:

<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE APIRequest SYSTEM "https://url">
<APIRequest>
  <Head>
    <Key>123</Key>
  </Head>
  <ObjectClass>
    <Field>Value</Field>
  </ObjectClass>
</APIRequest>

123
价值
代码:

使用系统;
使用系统诊断;
使用系统文本;
使用System.Xml;
使用System.Xml.Serialization;
公共静态类程序{
公共静态void Main(){
var obj=新对象类{Field=“Value”};
var设置=新的XmlWriterSettings{
缩进=真
};
var xml=新的StringBuilder();
使用(var writer=XmlWriter.Create(xml,设置)){
Assert(writer!=null);
writer.WriteDocType(“APIRequest”,null,”https://url“,空);
writer.writeStarteElement(“APIRest”);
作者。书面声明(“头”);
WriteElementString(“Key”,“123”);
writer.WriteEndElement();//
var nsSerializer=新的XmlSerializerNamespaces();
nsSerializer.Add(“,”);
var xmlSerializer=新的xmlSerializer(obj.GetType(),“”);
serializer.Serialize(writer、obj、nsSerializer);
writer.WriteEndElement();//
}
WriteLine(xml.ToString());
Console.ReadLine();
}
}
[XmlRoot(“ObjectClass”)]
公共类对象类{
[XmlElement(“字段”)]
公共字符串字段{get;set;}
}

派生您自己的XmlTextWriter以省略XML声明

Private Class MyXmlTextWriter
Inherits XmlTextWriter
Sub New(ByVal sb As StringBuilder)
    MyBase.New(New StringWriter(sb))
End Sub
Sub New(ByVal w As TextWriter)
    MyBase.New(w)
End Sub

Public Overrides Sub WriteStartDocument()
    ' Don't emit XML declaration
End Sub
Public Overrides Sub WriteStartDocument(ByVal standalone As Boolean)
    ' Don't emit XML declaration
End Sub
End Class
使用派生MyXmlTextWriter的实例调用Serialize

Dim tw As New MyXmlTextWriter(sb)
Dim objXmlSerializer As New XmlSerializer(type)
objXmlSerializer.Serialize(tw, obj)

在这方面有一个好帖子。不久前,我使用了Kzu的例子(Scott的博客指出了这个例子),它非常有效。

一行,从字符串中删除第一行:

String.Join("\n", strXML.Split('\n').Skip(1).ToArray())
不优雅,但简洁。

试试这个:

internal static string ToXml(object obj)
{
  string retval = null;
  if (obj != null)
  {
    StringBuilder sb = new StringBuilder();
    using(XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = true }))
    {
      new XmlSerializer(obj.GetType()).Serialize(writer, obj);
    }
    retval = sb.ToString();
  }
  return retval;
}

如果出于性能等原因不想依赖xml编写器,可以这样做:

// Read into memory stream and set namespaces to empty strings
XmlSerializerNamespaces nsSerializer = new XmlSerializerNamespaces();
nsSerializer.Add(string.Empty, string.Empty);
XmlSerializer xs = new XmlSerializer(typeof(Model.AudioItem));
xs.Serialize(ms, item, nsSerializer);

// Read into UTF-8 stream and read off first line (i.e "<?xml version="1.0"?>")
StreamReader sr = new StreamReader(ms);
ms.Position = 0;
sr.ReadLine();
//读入内存流并将名称空间设置为空字符串
XmlSerializerNamespaces nsSerializer=新的XmlSerializerNamespaces();
nsSerializer.Add(string.Empty,string.Empty);
XmlSerializer xs=新的XmlSerializer(typeof(Model.AudioItem));
序列化(ms、item、nsSerializer);
//读入UTF-8流并读出第一行(即“”)
StreamReader sr=新的StreamReader(毫秒);
ms.Position=0;
sr.ReadLine();
sr.ReadToEnd().ToString()现在包含裸序列化

if(!string.IsNullOrEmpty(strXML)和&strXML.contains(@“”,0)+2);
if (!string.IsNullOrEmpty(strXML) && strXML.Contains(@"<?xml"))
strXML = strXML.Remove(0, strXML.IndexOf(@"?>", 0) + 2);

谢谢,我知道字符串concat不好,但我认为它至少会起作用-我想不会!谢谢:-)我不会说这是邪恶的。它不是首选,但是如果您遇到性能至关重要的情况,并且您已经确定编写器是性能影响的来源,那么使用字符串连接可以是一个巨大的胜利。当然,它是情境的,我几乎总是使用<代码> XmlWriter <代码>,但在某些情况下,它是有道理的。@道格D:我很难相信你认为这是一个更好的解决办法。这正是Doug D一个月前说的-1.谢谢,但是对.NET 2.0有什么想法吗?自动?您似乎正在手动添加声明:w.WriteLine(@“”)@Cerburus,他不想要标记内部。@John DataContractSeAlizer不创建头
DataContractSerializer
也不发出DTD声明。对于ReadLine技巧,他感觉脏,但很聪明。我喜欢。任何有关缩进的问题,例如?strXML=strXML.Remove(0,sXMLContent.IndexOf(@“>”,0)+2);你能解释一下你的答案吗?