问题
I am using this method to serialize my object:
public static string XmlSerialize(object o)
{
var stringWriter = new StringWriter();
var xmlSerializer = new XmlSerializer(o.GetType());
xmlSerializer.Serialize(stringWriter, o);
string xml = stringWriter.ToString();
stringWriter.Close();
return xml;
}
It makes XML that starts like this:
<?xml version="1.0" encoding="utf-16"?>
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
But I want it to look like this:
<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?>
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
So, how do I change the encoding to Windows-1252 and set standalone = yes? Additionally, how to I get the object to exclude the xmlns value?
I've seen a couple similar questions, like this one, but I was hoping it might be simpler for me, maybe by setting some attributes somewhere?
Update 2: After looking at John's answer and comments, and thinking about this more, I decided to just make a second method. I don't think that creating this wacky custom xml just for a 3rd party on one occasion should be called something as generic as "XmlSerialize" in the first place.
So, I created a second method that takes an XML document and first, removes the one namespace element like this:
xElement.Attributes().Where(a => a.IsNamespaceDeclaration && a.Value == "http://www.w3.org/2001/XMLSchema").Remove();
then, it it writes it to XML with John's code. Finally it returns that xml, following the output from this:
new XDeclaration("1.0", "Windows-1252", "yes").ToString()
And that's ugly, but it gets me exactly what I need for this 3rd party to understand my XML.
回答1:
Try this:
public static string XmlSerialize(object o)
{
using (var stringWriter = new StringWriter())
{
var settings = new XmlWriterSettings
{
Encoding = Encoding.GetEncoding(1252),
OmitXmlDeclaration = true
};
using (var writer = XmlWriter.Create(stringWriter, settings))
{
var xmlSerializer = new XmlSerializer(o.GetType());
xmlSerializer.Serialize(writer, o);
}
return stringWriter.ToString();
}
}
This won't get rid of the xsd: namespace, but then, why do you want to?
Update: It seems that whenever you use a StringWriter
, you get UTF-16, even if you use an XmlWriter
on top of it with encoding set. Next step would be to write out to a MemoryStream
. But that raises the question of why you want to return a string. For instance, if you're going to just turn around and output the string to a stream, then we should output directly to this stream. Same for a TextWriter
.
回答2:
You can use an XmlTextWriter instead of a StringWriter. Here is an extract from some of my code with your encoding set.
XmlTextWriter textWriter = new XmlTextWriter(stream, Encoding.GetEncoding(1252));
textWriter.Namespaces = false;
回答3:
FWIW, I got the encoding to work by using an XmlWriter with XMLWriterSettings. Here is a sample:
...
// My object type was from a class generated by xsd.
XmlSerializer xms = new XmlSerializer(typeof(SomeType));
SomeType objSt;
using(FileStream fs = new FileStream("C:\SomeFile.xml", FileMode.Open, FileAccess.Read))
{
using(XmlReader xr = XmlReader.Create(fs)) // Supposed to preserve encoding.
{
objSt = (SomeType)xms.Deserialize(xr);
}
}
...
... // Do some stuff, change some attribute values.
...
XmlWriterSettings xsw= new XmlWriterSettings();
xsw.Indent= true;
xsw.NewLineOnAttributes= true;
xsw.Encoding = Encoding.GetEncoding(1252);
using(XmlWriter xwXsw = XmlWriter.Create("C:\SomeFile_Changed.xml",xsw))
{
xms.Serialize(xwXsw, objSt);
}
...
... // Finish up and get out.
...
For some reason, I was able to get it all to work once just using the XmlSerializer object and serializing with a TextWriter, since according to MS help for XmlSerializer.Deserialize(XmlReader) "The XmlReader automatically detects and uses the encoding specified by the XML document." Then I started playing with the XmlWriterSettings and broke something....
来源:https://stackoverflow.com/questions/1429593/how-do-i-control-the-xml-part-of-xml-serialization-with-net