XML Serializer

Q

Q. John Chen

I have following code:
public class Member
{
public string FirstName;
public string LastName;

public string GetXml()
{
StringBuilder sb = new StringBuilder();
XmlSerializer serializer
= new XmlSerializer(typeof(Member));
TextWriter writer = new StringWriter(sb);
serializer.Serialize(writer, this);
writer.Close();

return sb.ToString();

}
}

The above code create following piece of xml by Calling GetXml()

<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<Member
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n
<FirstName>John</FirstName>\r\n <LastName>Doe</LastName>\r\n
</Member>

But All I want is

<Member><FirstName>John</FirstName><LastName>Doe</LastName></Member>

Of course I can modify the string to take out the unwanted.

Is there a better way to just get what I wanted ??

Thanks

John
 
G

Guest

When the Serializer builds the string, it used the default formatted output,
in order to override that you will need to use an XmlTextWriter in addition
to the TextWriter, to do so, try changing your line of:

TextWriter writer = new StringWriter(sb);

and replacing it with:

XmlTextWriter writer = new XmlTextWriter( new StringWriter(sb) );
xmlWriter.Formatting = Formatting.None;

With this method, you are instructing the XmlWriter (that will be ultimately
responsible for outputting the file to whatever) not to use any special
formatting so that you end up with your nice long string.

Brendan
 
Q

Q. John Chen

Thanks for you help. I am one step closer now. This removed the \r\n.

I also want to remove:

<?xml version=\"1.0\" encoding=\"utf-16\"?>

and all the xmlns stuff.


How can I do that?

Thanks

John
 
Q

Q. John Chen

I noticed that XmlTextWriter has a NameSpace property.

So I added
xmlWriter.Namespaces = false;
ahead of xmlWriter.Formatting = ...

Got InvalidOperationException.

The doc says: "You can only change this property when in the
WriteState.Start state."

But I set it before writing anthing. Anyway, how can I set this value
without getting the exception.

Thanks

John
 
G

Guest

In order to remove that info as well you will need to create your own custom
XmlTextWriter, take this one for example as found several places on the
usenet:

public class XmlTextWriterFormattedNoDeclaration :
System.Xml.XmlTextWriter
{
public XmlTextWriterFormattedNoDeclaration( System.IO.TextWriter w) :
base(w)
{
Formatting= System.Xml.Formatting.Indented;
}
public override void WriteStartDocument() { }
}

In this code, the WriteStartDocument method which is responsible for the
header information you want to do away with is overloaded and when called
does nothing.

The nice thing about using that class is that you no longer have to manually
set the Formatting property to None as it is done so by the class... as for
the xmlns... give me a few min to try to locate the best method to override
for that.

Brendan
 
G

Guest

Got it.

Before calling serialize, add in:

XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);

Finally, add namespaces as the third argument to Serialize().

Brendan
 
Q

Q. John Chen

You almost saved day. Thanks a lot.

Here is my revised code

public class Member
{
public string FirstName;
public string LastName;
public DateTime JoinDate;

public string GetXml()
{
StringBuilder sb = new StringBuilder();

XmlSerializerNamespaces namespaces
= new XmlSerializerNamespaces();

namespaces.Add(string.Empty, string.Empty);

XmlSerializer serializer
= new XmlSerializer(typeof(Member));
TextWriter writer = new StringWriter(sb);
serializer.Serialize(writer, this, namespaces);
writer.Close();

return sb.ToString();

}

Notice that I actually have a DateTime field JoinDate. I am taking
advantage of the Serializer to format it correctly into Xml's date
type. No the the namespace gets into the JoinDate.

<JoinDate xmlns:q1=\"http://www.w3.org/2001/XMLSchema\"
d2p1:type=\"q1:dateTime\"
xmlns:d2p1=\"http://www.w3.org/2001/XMLSchema-instance\">2005-07-06T00:00:00.0000000-05:00</JoinDate
I may just make it a string field and format it by myself. Also,
DateTime is value typed and I have to boxing and unboxing it to
accommodate null value anyway.

Thanks again.

John
 
G

Guest

Try the following:

public class Member
{
internal class XmlTextWriterFormattedNoDeclaration :
System.Xml.XmlTextWriter
{
public XmlTextWriterFormattedNoDeclaration (System.IO.TextWriter
w) :
base(w) { Formatting= System.Xml.Formatting.None;}
public override void WriteStartDocument () { }
}

public string FirstName;
public string LastName;
public DateTime JoinDate;

public string GetXml()
{
StringBuilder sb = new StringBuilder();

XmlSerializerNamespaces namespaces
= new XmlSerializerNamespaces();

namespaces.Add(string.Empty, string.Empty);

XmlSerializer serializer
= new XmlSerializer(typeof(Member));
XmlTextWriterFormattedNoDeclaration writer = new
XmlTextWriterFormattedNoDeclaration(new StringWriter(sb));
serializer.Serialize(writer, this, namespaces);
writer.Close();

return sb.ToString();

}
}

I've run through it a number of times and works for me as far as I can tell
based on what you said you were looking for.

Brendan
 
Q

Q. John Chen

I found the problem why there are namespace in the <JoinDate>.

I defined it as type object so it can have a null value. That's the
whole purpose of what I am doing - Only generate the fields that have
values.

private object joinDate = null;

[XmlElement(ElementName = "JOIN_DATE")]
[XmlElementAttribute(IsNullable = false)]
public object JoinDate
{
get
{
if (joinDate == null)
return null;
else
return (DateTime) joinDate;
}

set { joinDate = value; }
}

I am on a tight project and don't much time research and experiment. I
was weighing do it the better way or just make it work. it was using
DataSet to get the xml. All the Tag name are different than field names
and constants are defined everywhere and lots of if (null or
string.Empty).

Thanks a million and the day, and the night, was saved.

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top