need to add comments in an existing xml document - c#

I need to add comments in an existing xml document.a sample xml is shown below i need to write code in c#. XML serialization was used to generate this xml
any help would be great...
thanks in advance
<?xml version="1.0" encoding="utf-8"?>
<Person>
<Name>Job</Name>
<Address>10dcalp</Address>
<Age>12</Age>
</Person>

Try it like this:
string input = #"<?xml version=""1.0"" encoding=""utf-8""?><Person><Name>Job</Name><Address>10dcalp</Address><Age>12</Age></Person>";
XDocument doc = XDocument.Parse(input);
XElement age = doc.Root.Element("Age");
XComment comm = new XComment("This is comment before Age");
age.AddBeforeSelf(comm);
This code gets the document, finds the element named "Age" which is expected to be under the root element ("Person") and adds comment before it.

You can use XmlWriter to write the comment in following way:
MemoryStream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream);
writer.WriteStartDocument();
writer.WriteComment("Add comment here");
Now, you serialize XmlWriter instance through your serializer.

Related

Parsing wrongly formatted XML-SOAP with C#

I have malformed XML (SOAP) file which I need to parse. The issue is that XML doesn't have proper header tags.
I've tried to parse file with XDocument and XmlDocument but neither has worked. XML starts from the line 30, so maybe there is some way to skip those lines before file is read by XML parser?
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:eb="http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd">
<SOAP-ENV:Header>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="Finvoice.xsl"?>
<GGVersion="2.01" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="a.xsd">
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader r = XmlReader.Create(file.FullName, settings);
XmlDocument xDoc = new XmlDocument();
xDoc.PreserveWhitespace = true;
xDoc.LoadXml("<xml/>");
xDoc.DocumentElement.CreateNavigator().AppendChild(r);
XmlNamespaceManager manager = new XmlNamespaceManager(xDoc.NameTable);
Once trying to parse I get: Unexpected xml declaration. The xml declaration must be the first node in the document ....
If I understand you correctly, then the data you are looking for starts after the SOAP envelope. There is no garbage/unnessescary contents after the data you are looking for.
The SOAP header does not start with the XML declaration (<?xml version=, etc).
Looking for the start of the document
A simple solution is to find the start of the XML document (the data you are looking for), and chop away everything before that.
var startOfRealDocumentMarker = "<?xml version=\"1.0\"";
var startIndex = dirtyXmlString.IndexOf(startOfRealDocumentMarker);
if(startIndex == -1) {
throw new Exception("Start of XML not found. Now what?");
}
var cleanXmlString = dirtyXmlString.Substring(startIndex);
If the SOAP header also has an XML declaration, you could look for the end-tag of the SOAP envelope instead. Or you could start looking for the declaration at the 2nd character, so you would skip over the first one.
This is obviously not a fool-proof solution that will work in every case. But maybe it will work in all of your cases?
Skipping lines
If you're sure it will work to always start reading from line 30 of the input file, you can use this method instead.
XmlDocument xDoc = new XmlDocument();
using (var rdr = new StreamReader(pathToXmlFile))
{
// Skip until reader is positioned at start of line 30
for (var i = 0; i < 29; ++i)
{
rdr.ReadLine();
}
// Load document from current position of reader
xDoc.Load(rdr);
}

Remove comments from an XML file with double dashes --

How can I remove invalid xml comments that contain double dashes(--) from an xml file?
I'm trying to load the xml file, but it is failing. These comments make the xml invalid. The xml comes from a vendor.
I tried removing these based on approaches from other posts, but I was not successful. Here is an example of the xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--MAIN VARIABLES-->
<content type="screwed">
<!--KEEP 19-39 -- SEE HELP.TXT AND THE VIDEO TUTORIALS FOR MORE INFO -->
<!--REGULAR/NON-Regular EXAMPLE --><SomeTag somefile="test.txt3" Name="test"/>
<!-- -->
</content>
I have tried the following without success:
string xmlDocFile = "c:\server\test.xml";
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.IgnoreComments = true;
readerSettings.ProhibitDtd = false;
readerSettings.ValidationType = ValidationType.DTD;
XmlReader reader = XmlReader.Create(xmlDocFile, readerSettings);
XmlDocument myXmlDoc = new XmlDocument();
myXmlDoc.Load(reader);
myXmlDoc.Save(xmlDocFile);
Before using XmlReader, parse xml file and filter comments using regexp.
// using System.Text.RegularExpressions;
System.IO.StreamReader file= new System.IO.StreamReader(xmlDocFile);
string validXml = Regex.Replace(file.ReadToEnd(),"<!--.*?-->","");
XmlReader reader = XmlReader.Create(validXml);

Reading XML file and indenting

I've been having problems with the indentation of my XML files. Everytime I load them from a certain server, the XML nodes all jumble up on a few lines. I want to write a quick application to indent the nodes properly. That is:
<name>Bob<name>
<age>24</age>
<address>
<stnum>2</stnum>
<street>herp derp st</street>
</address>
currently it's coming out as :
<name>bob</name><age>24</age>
<address>
<stnum>2</stnum><street>herp derp st</street>
</address>
since I can't touch the internal program that gives me these xml files and re-indenting them without a program would take ages, I wanted to write up a quick program to do this for me. When I use the XMLdocument library stuff, it only reads the information of the nodes. So my question is, whats a good way to read the file, line by line and then reindenting it for me. All xml nodes are the same.
Thanks.
You can use the XmlTextWritter class. More specifically the .Formatting = Formatting.Indented.
Here is some sample code I found on this blog post.
http://www.yetanotherchris.me/home/2009/9/9/formatting-xml-in-c.html
public static string FormatXml(string inputXml)
{
XmlDocument document = new XmlDocument();
document.Load(new StringReader(inputXml));
StringBuilder builder = new StringBuilder();
using (XmlTextWriter writer = new XmlTextWriter(new StringWriter(builder)))
{
writer.Formatting = Formatting.Indented;
document.Save(writer);
}
return builder.ToString();
}
With LINQ to XML, it's basically a one-liner:
public static string Reformat(string xml)
{
return XDocument.Parse(xml).ToString();
}
Visual Studio or any decent XML editor will format (tabify) XML documents easily. There are also on-line tools available:
http://www.xmlformatter.net/
http://www.shell-tools.net/index.php?op=xml_format
If you are using Visual studio just open xml do Ctrl+a Ctrl+k Ctrl+F and that's it for formatting.
You can also use XSLT:
// This XSLT copies everything but idented
StringReader sr = new StringReader( xsl );
XmlReader reader = XmlReader.Create(sr);
XslTransform xslt = new XslTransform();
xslt.Load(reader);
xslt.Transform(xmlFileUnidentedPath, xmlFileIdentedPath);
Having xsl defined as:
string xsl = #"
<?xml version=""1.0""?>
<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
<xsl:output method=""xml"" omit-xml-declaration=""no"" indent=""yes"" encoding=""US-SCII""/>
<xsl:strip-space elements=""*""/>
<xsl:template match=""/"">
<xsl:copy-of select="".""/>
</xsl:template>
</xsl:stylesheet>";

How to read processing instruction from an XML file using .NET 3.5

How to check whether an Xml file have processing Instruction
Example
<?xml-stylesheet type="text/xsl" href="Sample.xsl"?>
<Root>
<Child/>
</Root>
I need to read the processing instruction
<?xml-stylesheet type="text/xsl" href="Sample.xsl"?>
from the XML file.
Please help me to do this.
How about:
XmlProcessingInstruction instruction = doc.SelectSingleNode("processing-instruction('xml-stylesheet')") as XmlProcessingInstruction;
You can use FirstChild property of XmlDocument class and XmlProcessingInstruction class:
XmlDocument doc = new XmlDocument();
doc.Load("example.xml");
if (doc.FirstChild is XmlProcessingInstruction)
{
XmlProcessingInstruction processInfo = (XmlProcessingInstruction) doc.FirstChild;
Console.WriteLine(processInfo.Data);
Console.WriteLine(processInfo.Name);
Console.WriteLine(processInfo.Target);
Console.WriteLine(processInfo.Value);
}
Parse Value or Data properties to get appropriate values.
How about letting the compiler do more of the work for you:
XmlDocument Doc = new XmlDocument();
Doc.Load(openFileDialog1.FileName);
XmlProcessingInstruction StyleReference =
Doc.OfType<XmlProcessingInstruction>().Where(x => x.Name == "xml-stylesheet").FirstOrDefault();

Xml root node not closed

I'm using xmlwriter to create an xml document. The xml document looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<ExceptionsList />
How can i prevent the /> and appropriately end the root node?
Because of this, i can't append anything to the root node.
My code for creating the xml file looks like this:
string formatDate = DateTime.Now.ToString("d-MMM-yyyy");
XmlTextWriter xmlWriter = new XmlTextWriter(xmlfileName, Encoding.UTF8);
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.Indentation = 3;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("ExceptionsList"); // ExceptionsList (Root) Element
xmlWriter.WriteEndElement(); // End of ExceptionsList (Root) Element
xmlWriter.WriteEndDocument();
xmlWriter.Flush();
xmlWriter.Close();
And I append to the root node like this:
XDocument xml = XDocument.Load(xmlFileName);
XElement root = xml.Root;
root.Add(new XElement("Exception",
new XElement("Exception Type", exceptionType),
new XElement("Exception Message", exceptionMessage),
new XElement("InnerException", innerException),
new XElement("Comment", comment)));
xml.Save(xmlFileName);
This gives me a stackoverflow at runtime error too.
Any help would be appreciated.
Thanks in advance!
Your code is right, and you don't need to change how your ExceptionsList element is closed.
xmlWriter.WriteStartElement("ExceptionsList"); // ExceptionsList (Root) Element
xmlWriter.WriteStartElement("Exception"); // An Exception element
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement(); // End of ExceptionsList (Root) Element
In your second snippet, you need to remove those white spaces from element name, as XML specification forbid that and add your elements into your XDocument instance, like this:
XDocument xml = new XDocument();
xml.Add(new XElement("Exception",
new XElement("ExceptionType", "Exception"),
new XElement("ExceptionMessage",
new XElement("InnerException", "innerException")),
new XComment("some comment")));
xml.Save("sample2.xml");
I believe the problem is here:
new XElement("Exception Type", exceptionType),
new XElement("Exception Message", exceptionMessage),
Neither Exception Type nor Exception Mesage is a valid name for an xml element. Then of course, if you use this (doomed) method to log the error... stack overflow.

Categories