Make xml more readable - c#

Is there any way to take an xml string in .net and make it easyer to read?
what i mean is can i convert this:
<element1><element2>some data</element2></element1>
to this:
<element1>
<element2>
some data
</element2>
</element1>
is there any built in class for this? as sql server 2005 seems to remove all formatting on xml to save space or some thing...

If you're using .NET 3.5, you can load it as an XDocument and then just call ToString() which will indent it appropriately. For example:
using System;
using System.Xml.Linq;
public class Test
{
static void Main()
{
string xml = "<element1><element2>some data</element2></element1>";
XDocument doc = XDocument.Parse(xml);
xml = doc.ToString();
Console.WriteLine(xml);
}
}
Result:
<element1>
<element2>some data</element2>
</element1>
If you're writing it to a file or other stream, then XDocument.Save will (by default) indent it too.
(I believe XElement has all the same features, if you don't really need an XDocument.)

How do you save / write the XML back to a file ?
You can create an XmlWriter and pass it an XmlWriterSettings instance, where you set the Indent property to true:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create (outputStream, settings);

You can load the string into an XDocument object and save it to a string again:
XDocument doc = XDocument.Load(new StringReader(xmlString));
StringWriter writer = new StringWriter();
doc.Save(writer);
string readable = writer.ToString();
That will give you the xml formatted this way:
<?xml version="1.0" encoding="utf-16"?>
<element1>
<element2>some data</element2>
</element1>

Have a look at
XmlWriterSettings
http://msdn.microsoft.com/en-us/library/system.xml.xmlwritersettings.aspx
you can define Indent and IndentChars

First of all, you have tagged C# and VB.NET both. So my answer will be for both of them.
You can define function which get XML string as a parameter in type of String.
Let's say;
You created a function as :
[VB]
Private Function PrettyXML(XMLString As String) As String
Dim sw As New StringWriter()
Dim xw As New XMLWriter(sw)
xw.Formatiing = Formatting.Indented
xw.Indentation = 4
Dim doc As New XMLDocument
doc.LoadXML(XMLString)
doc.Save(xw)
Return sw.ToString()
End Function
Then you can simpyl call this function as:
Dim myXML As String = "<element1><element2>some data</element2></element1>"
Dim myPrettyXML As String
myPrettyXML = PrettyXML(myPrettyXML)
[C#]
Private String PrettyXML(string XMLString)
{
StringWriter sw = new StringWriter();
XMLTextWriter xw = new XmlTextWriter(sw);
xw.Formatiing = Formatting.Indented;
xw.Indentation = 4;
XmlDocument doc = new XmlDocument();
doc.Save(xm);
return sw.ToString();
}
Then you can simply call this function as:
string myXML = "<element1><element2>some data</element2></element1>";
string myPrettyXML = "";
myPrettyXML = PrettyXML(myPrettyXML);
NOTE: I have not tried C# version, but it should work.
Hope this helps..

Related

How Can I add XML declaration?

I Have this Xml output from URL XML
using HTTP GET method
How Can I add this XML declaration?
?xml version="1.0" encoding="ISO-8859-1"?>
This is ServiceContract
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Xml,
//BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "{id}")]
XElement GetRecipesByID(string id);
This is implementation,
I convert DataTable To Xml and get from URL
public XElement GetRecipesByID(string id)
{
StringWriter str = new StringWriter();
DataSet dataSet = new DataSet();
dataSet.Tables.Add(Table);
XmlTextWriter xtext = new XmlTextWriter(str);
xtext.Formatting = Formatting.Indented;
xtext.WriteStartDocument();
xtext.WriteStartElement("rss");
xtext.WriteAttributeString("version", "2.0");
xtext.WriteStartElement("channel");
xtext.WriteElementString("title", "GetCard");
xtext.WriteElementString("link", "10.0.0.253");
xtext.WriteElementString("lastBuildDate", " ");
xtext.WriteElementString("generator", "Alikas Feed");
xtext.WriteElementString("error", error);
xtext.WriteElementString("cardid", "RX0016502");
xtext.WriteElementString("name", " ");
xtext.WriteElementString("passport_id", "60001082881");
xtext.WriteElementString("tel", " ");
xtext.WriteEndElement();
xtext.WriteEndDocument();
result = str.ToString();
xtext.Close();
XmlDocument doc = new XmlDocument();
doc.Save(str);
return XElement.Parse(result);
}
When I save this xml in file there is xml declaration but when I try to get this xml from URL xml declaration doesn't show.
I need to show this declaration from URL.
Thank you
WriteStartDocument should already be adding the XML declaration. It uses the Encoding specified by your TextWriter.
You're using a StringWriter which will always report UTF-16 as .NET Strings are in UTF-16. To get ISO-8859-1, you'll need to construct a StreamWriter or some other TextWriter with an explicit encoding.
Have you considered creating an XDocument directly? No need to use XmlWriter in that case.
Try following :
string header = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><rss version=\"2.0\"/>";
XDocument doc = XDocument.Parse(header);
XElement rss = doc.Root;
Boolean error = false;
rss.Add(new XElement("channel", new object[] {
new XElement("title", "GetCard"),
new XElement("link", "10.0.0.253"),
new XElement("lastBuildDate", " "),
new XElement("generator", "Alikas Feed"),
new XElement("error", error),
new XElement("cardid", "RX0016502"),
new XElement("name"),
new XElement("passport_id", "60001082881"),
new XElement("tel")
}));
doc.Save(#"c:\temp\test.xml");
There is an special method for this:
var xmlDoc = new XmlDocument();
xmlDoc.CreateXmlDeclaration("1.0", "ISO-8859-1", null);
xmlDoc.Save(str);
Note from the msdn on encoding parameter: This is the encoding that is used when you save the XmlDocument to a file or a stream; therefore, it must be set to a string supported by the Encoding class, otherwise Save fails.
This seems to work for me
XDocument xel = XDocument.Parse( "<root><el>123</el></root>" );
xel.Declaration = new XDeclaration( "1.0","UTF-8","true" );
xel.Save( #"c:\temp.xml" );

How to include Declaration with XElement.ToString()

I am trying to write an XML response for my web service however I can't figure out how to make the declaration appear in the response.
My code is like so :
StringBuilder sBuilder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sBuilder))
{
writer.WriteStartDocument();
writer.WriteStartElement("ReportResponse");
Response.WriteXml(writer);
writer.WriteEndElement();
writer.WriteEndDocument();
}
var response = XElement.Parse(sBuilder.ToString());
return response;
Response is just a POCO for storing response data.
I am aware that the Save method includes the declaration and the ToString() method does not. I need to write my declaration back with ToString().
I really just want to return custom XML from my REST Service without casting my string 100 times to return valid XML. Is this even possible or am just spinning my wheels ?
If you want to include xml declaration, you can do it this way:
XDocument xdoc = XDocument.Parse(xmlString);
StringBuilder builder = new StringBuilder();
using (TextWriter writer = new StringWriter(builder))
{
xdoc.Save(writer);
}
Console.WriteLine(builder);
Update:
I've noticed, that StringWriter spoils encoding. So one more option is to do so:
string docWithDeclaration = xdoc.Declaration + xdoc.ToString();

Transforming Xml into valid Html fragments through Xslt using .NET XslCompiledTransform class

I am trying to use XslCompiledTransform in the .NET class library in order to transform an xml string to an Html string. Please consider that I want to use normal strings, not files.
How ca I do this?
It seems that XslCompiledTransform only works with files...
Load() also accepts XmlReader, and Transform() accepts most combinations of XmlReader input, and XmlWriter, TextWriter and Stream as output.
So most typically, you might use a StringWriter for the output, and a XmlReader created from a StringReader for the input.
Full example, no files:
string xslt = #"<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
<xsl:output method=""html"" indent=""no""/>
<xsl:template match=""*"">
<p>some html</p>
</xsl:template>
</xsl:stylesheet>", xml = #"<xml>boo</xml>";
var transform = new XslCompiledTransform();
using (var sr = new StringReader(xslt))
using (var xr = XmlReader.Create(sr))
{
transform.Load(xr);
}
using (var sw = new StringWriter())
using (var sr = new StringReader(xml))
using (var xr = XmlReader.Create(sr))
{
transform.Transform(xr, null, sw);
string html = sw.ToString();
}
I have use xslt and xml in the form of string ,
which is generated on the same .aspx page,
then converting it to html using StringWriter,
use a literal control to show html,bind Stringwriter data to it.
string xslt="Add your code for xslt here";//look for any normal xslt file.
string xml="Add your code for xml here";//look for any normal xml file.
XslCompiledTransform transform = new XslCompiledTransform();
StringReader sr = new StringReader(xslt);
XmlReader xr = XmlReader.Create(sr);
transform.Load(xr);
StringReader srxml = new StringReader(xml);
XmlReader xrxml = XmlReader.Create(srxml);
StringWriter writer = new StringWriter();
transform.Transform(xrxml, null, writer);
Literal1.Text = writer.ToString();
writer.Close();

Prevent XmlSerializer from formatting output

When using the default settings with the XmlSerializer it will output the XML as a formated value.
IE: something along these lines.
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfStock xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Stock>
<ProductCode>12345</ProductCode>
<ProductPrice>10.32</ProductPrice>
</Stock>
<Stock>
<ProductCode>45632</ProductCode>
<ProductPrice>5.43</ProductPrice>
</Stock>
</ArrayOfStock>
How does one prevent any type of formatting on the output? So what I am looking to achieve is this.
<?xml version="1.0" encoding="utf-8"?><ArrayOfStock xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Stock><ProductCode>123456</ProductCode><ProductPrice>10.57</ProductPrice></Stock><Stock><ProductCode>789123</ProductCode><ProductPrice>133.22</ProductPrice></Stock></ArrayOfStock>
EDIT: The full code of my method is
public static String Serialize(Stock stock)
{
XmlSerializer serializer = new XmlSerializer(typeof(Stock));
using (StringWriter stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, stock);
return stringWriter.ToString();
}
}
Not very intuitive, but the Indent property on the XmlWriterSettings controls the whole formatting:
var serializer = new XmlSerializer(typeof(MyClass));
using (var writer = new StreamWriter("file.path"))
using (var xmlWriter = XmlWriter.Create(writer, new XmlWriterSettings { Indent = false }))
{
serializer.Serialize(xmlWriter, myObject);
}
There are a few more options on XmlWriterSettings that you might want to explore.
It is simple to parse the resulting XML and remove and newlines and tabs...
using 'Indent = false', will still put elements on newlines no?
..
XmlSerializer xmlser = new XmlSerializer(...);
XmlWriterSettings settings = new XmlWriterSettings {Indent = false};
using (XmlWriter xw = XmlWriter.Create(stream, settings))
{
...

XML indenting when injecting an XML string into an XmlWriter

I have an XmlTextWriter writing to a file and an XmlWriter using that text writer. This text writer is set to output tab-indented XML:
XmlTextWriter xtw = new XmlTextWriter("foo.xml", Encoding.UTF8);
xtw.Formatting = Formatting.Indented;
xtw.IndentChar = '\t';
xtw.Indentation = 1;
XmlWriter xw = XmlWriter.Create(xtw);
Changed per Jeff's MSDN link:
XmlWriterSettings set = new XmlWriterSettings();
set.Indent = true;
set.IndentChars = "\t";
set.Encoding = Encoding.UTF8;
xw = XmlWriter.Create(f, set);
This does not change the end result.
Now I'm an arbitrary depth in my XmlWriter and I'm getting a string of XML from elsewhere (that I cannot control) that is a single-line, non-indented XML. If I call xw.WriteRaw() then that string is injected verbatim and does not follow my indentation I want.
...
string xml = ExternalMethod();
xw.WriteRaw(xml);
...
Essentially, I want a WriteRaw that will parse the XML string and go through all the WriteStartElement, etc. so that it gets reformatted per the XmlTextWriter's settings.
My preference is a way to do this with the setup I already have and to do this without having to reload the final XML just to reformat it. I'd also prefer not to parse the XML string with the likes of XmlReader and then mimic what it finds into my XmlWriter (very very manual process).
At the end of this I'd rather have a simple solution than one that follows my preferences. (Best solution, naturally, would be simple and follows my preferences.)
How about using a XmlReader to read the xml as xml nodes?
string xml = ExternalMethod();
XmlReader reader = XmlReader.Create(new StringReader(xml));
xw.WriteNode(reader, true);
You shouldn't use XmlTextWriter, as indicated in MSDN where it states:
In the .NET Framework version 2.0
release, the recommended practice is
to create XmlWriter instances using
the XmlWriter.Create method and the
XmlWriterSettings class. This allows
you to take full advantage of all the
new features introduced in this
release. For more information, see
Creating XML Writers.
Instead, you should use XmlWriter.Create to get your writer. You can then use the XmlWriterSettings class to specify things like indentation.
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = "\t";
Update
I think you can just use WriteNode. You take your xml string and load it into an XDocument or XmlReader and then use the node from that to write it into your XmlWriter.
This is the best I've got so far. A very manual process that only supports what is written. My string XML is nothing more than tags, attributes, and text data. If it supported namespaces, CDATA, etc. then this would have to grow accordingly.
Very manual, very messy and very likely prone to bugs but it does accomplish my preferences.
private static void PipeXMLIntoWriter(XmlWriter xw, string xml)
{
byte[] dat = new System.Text.UTF8Encoding().GetBytes(xml);
MemoryStream m = new MemoryStream();
m.Write(dat, 0, dat.Length);
m.Seek(0, SeekOrigin.Begin);
XmlReader r = XmlReader.Create(m);
while (r.Read())
{
switch (r.NodeType)
{
case XmlNodeType.Element:
xw.WriteStartElement(r.Name);
if (r.HasAttributes)
{
for (int i = 0; i < r.AttributeCount; i++)
{
r.MoveToAttribute(i);
xw.WriteAttributeString(r.Name, r.Value);
}
}
if (r.IsEmptyElement)
{
xw.WriteEndElement();
}
break;
case XmlNodeType.EndElement:
xw.WriteEndElement();
break;
case XmlNodeType.Text:
xw.WriteString(r.Value);
break;
default:
throw new Exception("Unrecognized node type: " + r.NodeType);
}
}
}
composing the answers above I have found this works:
private static string FormatXML(string unformattedXml) {
// first read the xml ignoring whitespace
XmlReaderSettings readeroptions= new XmlReaderSettings {IgnoreWhitespace = true};
XmlReader reader = XmlReader.Create(new StringReader(unformattedXml),readeroptions);
// then write it out with indentation
StringBuilder sb = new StringBuilder();
XmlWriterSettings xmlSettingsWithIndentation = new XmlWriterSettings { Indent = true};
using (XmlWriter writer = XmlWriter.Create(sb, xmlSettingsWithIndentation)) {
writer.WriteNode(reader, true);
}
return sb.ToString();
}
How about:
string xml = ExternalMethod();
var xd = XDocument.Parse(xml);
xd.WriteTo(xw);
I was looking for an answer to this issue but in VB.net.
Thanks to Colin Burnett, I solved it. I made two corrections: first, the XmlReader has to ignore white spaces (settings.IgnoreWhiteSpaces); second, the reader has to be back into the element after it reads attributes. Below you can see how the code looks like.
Also I tried the solution of GreyCloud, but in the generated XML there were some annoying empties attributes (xlmns).
Private Sub PipeXMLIntoWriter(xw As XmlWriter, xml As String)
Dim dat As Byte() = New System.Text.UTF8Encoding().GetBytes(xml)
Dim m As New MemoryStream()
m.Write(dat, 0, dat.Length)
m.Seek(0, SeekOrigin.Begin)
Dim settings As New XmlReaderSettings
settings.IgnoreWhitespace = True
settings.IgnoreComments = True
Dim r As XmlReader = XmlReader.Create(m, settings)
While r.Read()
Select Case r.NodeType
Case XmlNodeType.Element
xw.WriteStartElement(r.Name)
If r.HasAttributes Then
For i As Integer = 0 To r.AttributeCount - 1
r.MoveToAttribute(i)
xw.WriteAttributeString(r.Name, r.Value)
Next
r.MoveToElement()
End If
If r.IsEmptyElement Then
xw.WriteEndElement()
End If
Exit Select
Case XmlNodeType.EndElement
xw.WriteEndElement()
Exit Select
Case XmlNodeType.Text
xw.WriteString(r.Value)
Exit Select
Case Else
Throw New Exception("Unrecognized node type: " + r.NodeType)
End Select
End While
End Sub

Categories

Resources