xml data always being created as CDATA and not PCDATA - c#

I wrote a web service with C# , and i want one of his methods to return an XML.
i've managed to do so , but all the data is being tagged as CDATA and not being parsed. its not what i am looking for.
this is my code :
[WebMethod(EnableSession = true, Description = "Returns the safe activities for the required days period in XML")]
public string GetSafeActivitiesXML(string safename, int days, string FileName)
{
string returnErrorCode = "001";
try
{
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true
//IndentChars = " ",
//NewLineChars = "\n",
//NewLineHandling = NewLineHandling.None,
//Encoding = System.Text.Encoding.UTF8
};
StringWriter sb = new StringWriter();
XmlWriter writer = XmlWriter.Create(sb,settings);
writer.WriteStartDocument();
writer.WriteStartElement("GetSafeActivitiesResult", "");
int lineCouner = 0;
if (safeActivities.Count > 0)
{
writer.WriteStartElement("ListOfStrings", "");
foreach (ActivityLogRecord activity in safeActivities)
{
writer.WriteStartElement("string");
writer.WriteElementString("outFileName", (activity.Info1.Substring(activity.Info1.LastIndexOf("\\")+1)));
writer.WriteElementString("activityTmStamp", activity.Time.ToString());
writer.WriteElementString("userName", activity.UserName);
writer.WriteElementString("ActionID", activityCode);
writer.WriteElementString("direction", direction);
writer.WriteElementString("path", activity.Info1);
writer.WriteEndElement();
lineCouner++;
}
}
writer.WriteEndElement();
}
writer.WriteStartElement("retunCode");
writer.WriteString((lineCouner > 0) ? "0" : "2");
writer.WriteEndElement();
writer.WriteStartElement("retunMessage");
writer.WriteString((lineCouner > 0) ? "תקין" : "אין נתונים");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
XmlDocument xmlOut = new XmlDocument();
xmlOut.LoadXml(sb.ToString());
writer.Close();
//xmlOut.Save(xxx);
string finalOutput = sb.ToString();
finalOutput.Replace("![CDATA[", "").Replace("]]", "");
return sb.ToString();
}
catch (Exception ex)
{
this.LogWrite("GetSafeActivities", string.Format("Operation has failed: {0}, internal errorcode: {1}", ex.Message,returnErrorCode), Session.SessionID, true);
return string.Format("<ReturnCode>{0}</ReturnCode><ReturnMSG>{1}</ReturnMSG>", "שגוי", ex.Message) ;
}
}
This is an example for the current output:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetSafeActivitiesXMLResponse xmlns="http://www.securenet.co.il">
<GetSafeActivitiesXMLResult><![CDATA[<?xml version="1.0" encoding="utf-16"?>
<GetSafeActivitiesResult>
<ListOfStrings>
<string>
<outFileName>code-xmp-tmp.txt</outFileName>
<activityTmStamp>21/06/2015 10:58:38</activityTmStamp>
<userName>naaman</userName>
<ActionID>קובץ אוחסן בכספת</ActionID>
<direction>Unknown</direction>
<path>Root\fgdf\code-xmp-tmp.txt</path>
</string>
</ListOfStrings>
<retunCode>0</retunCode>
<retunMessage>תקין</retunMessage>
</GetSafeActivitiesResult>]]></GetSafeActivitiesXMLResult>
</GetSafeActivitiesXMLResponse>
</soap:Body>
This is what i want to achieve:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetSafeActivitiesXMLResponse xmlns="http://www.securenet.co.il">
<GetSafeActivitiesXMLResult><?xml version="1.0" encoding="utf-16"?>
<GetSafeActivitiesResult>
<ListOfStrings>
<string>
<outFileName>code-xmp-tmp.txt</outFileName>
<activityTmStamp>21/06/2015 10:58:38</activityTmStamp>
<userName>naaman</userName>
<ActionID>קובץ אוחסן בכספת</ActionID>
<direction>Unknown</direction>
<path>Root\fgdf\code-xmp-tmp.txt</path>
</string>
</ListOfStrings>
<retunCode>0</retunCode>
<retunMessage>תקין</retunMessage>
</GetSafeActivitiesResult></GetSafeActivitiesXMLResult>
</GetSafeActivitiesXMLResponse>
</soap:Body>
so my question really is , how to get rid of the CDATA tag, and why is it there on the first place.
i'm new to xml, so please be patient.

The output you want to achieve is XML that is not well-formed: you're essentially trying to nest an XML document, complete with an XML declaration (i.e. <?xml version="1.0" encoding="utf-16"?>), as literal character data within an XML document (or fragment) -- this is not a legal construct.
The proper way to include an XML document, or any text which would be recognized as markup, within another XML document (element) is to basically escape it by using a CDATA section so that it is not parsed as markup. And that is exactly what the web service/SOAP infrastructure is doing for you.
If it didn't do that and your XML text became parsed data (PCDATA) like you want, the consuming parser would throw an exception or return an error because your web service response XML would not be well-formed.

the method returned a String type, and that was the problem.
i changed the return type to XmlDocument, and now its all honey and nuts.

Related

Append Serialized Object Into XML in C#

I have a XML structer like that
<?xml version="1.0" encoding="utf-8"?>
<Product>
<ProductName>da</ProductName>
<PluginPath></PluginPath>
<Instances></Instances>
</Product>
and i serialize my object to string.
<?xml version="1.0"?>
<Instance xmlns:xsi="http://bla bla" xmlns:xsd="bla bla" UniqueId="d4820029b7d7">
<InstanceName>Instance MyTestPluginForm</InstanceName>
<Description>Test Plugin IW</Description>
<AddedDate>2016-10-19T11:05:10.7443404+02:00</AddedDate>
<LogSettings>
<LoggingLevel>None</LoggingLevel>
<LogFilePath /><MaximumSize>100</MaximumSize
<ClearAfterDays>7</ClearAfterDays>
<IsSaveActiviesToEventLog>false</IsSaveActiviesToEventLog>
</LogSettings>
<ProductSpecific/>
</Instance>
So I want to append the second one in the Instances node in the first xml. But as you see both has xml definition on the top and after serializazion i got xmlns:xsi and xmlns:xsd attributes.
How to solve this problem?
PS: I do not want to create XML elements. Because my xml schema is dynamic. It has to be done with serialization. (I already checked this sample)
I solved the problem. using the code here
public static void CreateXmlFile(Instance instance, string filePath)
{
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Product><ProductName>da</ProductName><PluginPath></PluginPath><Instances></Instances></Product>";
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
xmlDocument.Save(filePath);
XmlNode xnode = xmlDocument.CreateNode(XmlNodeType.Element, "Instances", null);
XmlSerializer xSeriz = new XmlSerializer(typeof(Instance));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings writtersetting = new XmlWriterSettings();
writtersetting.OmitXmlDeclaration = true;
StringWriter stringwriter = new StringWriter();
using (XmlWriter xmlwriter = System.Xml.XmlWriter.Create(stringwriter, writtersetting))
{
xSeriz.Serialize(xmlwriter, instance, ns);
}
xnode.InnerXml = stringwriter.ToString();
XmlNode bindxnode = xnode.SelectSingleNode("Instance");
xmlDocument.DocumentElement.SelectSingleNode("Instances").AppendChild(bindxnode);
xmlDocument.Save(filePath);
}

SqlXml removes XML header when comes from string

I'm developing a web app with C# and MVC4. Currently I'm working in converting string vars to SqlXml files. I have a XML file with this structure:
<?xml version="1.0" encoding="utf-8"?>
<cfdi:Comprobante xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/TimbreFiscalDigital/TimbreFiscalDigital.xsd" xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" version="3.2" xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</cfdi:Comprobante>
I'm converting the above file to string successfully and then I'm usign the following code that converts a string to a SqlXML.
cfdiDocumento.CFDIXML = Serializar.XMLToSqlXml(comprobante);
Where cfdiDocumento.CFDIXML is a SqlXml var, Serializar.XMLToSqlXml(comprobante) method receives a string and executes the following code:
public static SqlXml XMLToSqlXml(string xmlString)
{
SqlXml sqlXmlFiltro = null;
if (xmlString != null)
{
StringReader sr = new StringReader(xmlString);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Auto;
XmlReader reader0 = XmlReader.Create(sr, settings);
sqlXmlFiltro = new SqlXml(reader0);
}
return sqlXmlFiltro;
}
When the code finishes successfully, the file is correct but is removing the xml header
<?xml version="1.0" encoding="utf-8"?>
The question is: How do I preserve the xml header when convierting to SqlXml var?
If you cannot change the type of your SqlXml attribute, you could try converting the SqlXml to xml document to append xml declaration and get the outer xml:
public string SqlXmlToString(SqlXml sqlXml)
{
XmlDocument doc = new XmlDocument();
doc.Load(sqlXml.CreateReader());
// Create XML declaration with your encoding.
XmlDeclaration xmldecl;
xmldecl = doc.CreateXmlDeclaration("1.0", null, null);
xmldecl.Encoding = "UTF-8";
// Add to the document the created declaration
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xmldecl, root);
return doc.OuterXml;
}
Hope this is helpfully

Error trying to read an XML Document(C#)?

I have the following XML that I am trying to "load" into an XmlDocument object:Link to XML File
I have the following method piece of code to load the XML document:
public XmlDocument getDirections()
{
XmlTextReader xmlReader;
XmlDocument xmlResponse = new XmlDocument();
StringBuilder xmlResponseString = new StringBuilder();
xmlReader = new XmlTextReader(getRequestURL()); //getRequestURL gives the URL for XML doucument
while (xmlReader.Read())
{
if (xmlReader.NodeType == XmlNodeType.Element)
{
xmlResponseString.Append(xmlReader.ReadInnerXml());
}
}
xmlResponse.LoadXml(xmlResponseString.ToString());
return xmlResponse;
}
When I run the code, I get the following error:
An unhandled exception of type 'System.Xml.XmlException' occurred in System.Xml.dll
Additional information: There are multiple root elements. Line 3, position 3.
I figured this happens because the XML document have multiple route objects but I don't know how to fix it. Any help would be appreciated !
The line where it says:
Additional information: There are multiple root elements. Line 3, position 3.
This is your clue.
Properly formatted XML will have 1 root element.
Ex.
<root>
<child>
<subchild>.....</subchild>
</child>
</root>
See for a further explanation: http://www.w3schools.com/xml/xml_syntax.asp
What's the point of doing it that way? Use the built in functionality for getting Xml from a Url:
var str = #"https://maps.googleapis.com/maps/api/directions/xml?origin=Jamaica,%20NY%2011418&destination=Hunter%20College%20Park%20Avenue%20New%20York&mode=&alternatives=true&key=AIzaSyB8G9omVUu6a_OQCrRM-QItdwk-Hxq__mg";
var doc = new XmlDocument();
doc.Load(str);
//or
var xdoc = XDocument.Load(str);
I would look into Linq to Xml (XDocument) over XmlDocument. It's a lot easier to work with.
You can use following snippet to load xml.
public XmlDocument getDirections()
{
XmlTextReader xmlReader;
XmlDocument xmlResponse = new XmlDocument();
StringBuilder xmlResponseString = new StringBuilder();
HttpWebRequest request =HttpWebRequest.Create(getRequestURL());
using(HttpWebResponse response = (HttpWebResponse) request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
using (var responseStream = response.GetResponseStream())
{
xmlResponse.Load(responseStream);
}
}
}
xmlResponse.LoadXml(xmlResponseString.ToString());
return xmlResponse;
}
I came across a similar incident when trying to read an Xml using the XmlReader.
My code:
using (XmlReader reader = XmlReader.Create(new StringReader(filesContent)))
{
while (reader.Read()) //<--- This is where the exception was caught
{
// Do stuff here
}
}
The exception caught:
An unhandled exception of type 'System.Xml.XmlException' occurred in
System.Xml.dll
Additional information: There are multiple root elements. Line X,
position Y.
Note: The information regarding the location of the line and position which were provided in the exception were not the actual line or the position in the xml file content where my additional root was, making this a bit misleading.
A properly formatted xml file should contain only ONE root. As such:
<?xml version="1.0" encoding="UTF-8" ?>
<root1>
<child1>
<subchild1>.....</subchild1>
</child1>
</root1>
In my case the exception was being thrown because my xml file contained 2 roots.
<?xml version="1.0" encoding="UTF-8" ?>
<root1>
<child1>
<subchild1>.....</subchild1>
</child1>
</root1>
<root2>
<child1>
<subchild1>.....</subchild1>
<subchild2>.....</subchild2>
</child1>
<child2>
<subchild1>.....</subchild1>
</child2>
</root2>
This could easily be fixed by adding some 'parentroot' to the file, making the 2 roots nest under the new parent root as such
<?xml version="1.0" encoding="UTF-8" ?>
<parnetroot>
<root1>
<child>
<subchild>.....</subchild>
</child>
</root1>
<root2>
<child1>
<subchild1>.....</subchild1>
<subchild2>.....</subchild2>
</child1>
<child2>
<subchild1>.....</subchild1>
</child2>
</root2>
</parnetroot>

Append to an XML File using XMLWriter class in C#

I have a method which creates an xml file and this method is frequently called from other classes. I have sent three parameters to this method and while writing the xml file I need to append in the xml file with those three parameters. Here's my code snippet
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(#"E:\\log.xml", settings);
writer.WriteStartDocument();
writer.WriteStartElement("Log");
writer.WriteStartElement("Tests");
writer.WriteStartElement("Test");
writer.WriteAttributeString("Test", message);
writer.WriteElementString("DateAndTime", time);
writer.WriteElementString("Result", test);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
I get his output :
<?xml version="1.0" encoding="utf-8"?>
<Log>
<Tests>
<Test Test="LoginToAcrm">
<DateAndTime>2014-20-28 06:20:40</DateAndTime>
<Result>Passed</Result>
</Test>
</Tests>
</Log>
Can anyone please tell me what should I change in my code so that when I call the method again with these three parameters it will append to this xml file with the same format, not overwrite the previous file. Something will be like this:
<?xml version="1.0" encoding="utf-8"?>
<Log>
<Tests>
<Test Test="LoginToAcrm">
<DateAndTime>2014-20-28 06:20:40</DateAndTime>
<Result>Passed</Result>
</Test>
</Tests>
<Tests>
<Test Test="LoginToProjectWithError">
<DateAndTime>2014-09-28 05:10:45</DateAndTime>
<Result>Failed</Result>
</Test>
</Tests>
<Tests>
<Test Test="LoginToProjectWithBlank">
<DateAndTime>2014-09-28 05:12:13</DateAndTime>
<Result>Passed</Result>
</Test>
</Tests>
</Log>
I used some your code, use StringBuilder to create XmlWriter and finally write that string using StreamWriter.
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb, settings);
writer.WriteStartDocument();
writer.WriteStartElement("Tests");
writer.WriteStartElement("Test");
writer.WriteAttributeString("Test", message);
writer.WriteElementString("DateAndTime", time);
writer.WriteElementString("Result", test);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"E:\\log.xml", true))
{
file.Write(sb.ToString());
}
You can achieve this by passing List of strings as arguments to the function. And for your help i did the coding of the complete function. Let me know if this work out for you. Check this out
void xmlwriter(List<string> message, List<string> time, List<string> test)
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(#"E:\\log.xml", settings);
writer.WriteStartDocument();
writer.WriteStartElement("Tests");
string[] arrayMessage = message.ToArray();
string[] arrayTime = time.ToArray();
string[] arrayTest = test.ToArray();
for (int i = 0; i < arrayMessage.Length; i++)
{
writer.WriteStartElement("Test");
writer.WriteAttributeString("Test", arrayMessage[i]);
writer.WriteElementString("DateAndTime", arrayTime[i]);
writer.WriteElementString("Result", arrayTest[i]);
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
}
Note: You may have to add all the values of the parameters to the List before you call the function.
Your desired result isn't a well-formed XML document, since an XML document may only have a single root element.
However, if this is what you want (i.e. rather than an XML document, you want a text document containing XML fragments), you could try the following:
Open the existing file as a FileStream
Seek to the end of file
Pass the FileStream to your XmlWriter constructor
Append the elements you want

Remove standalone attribute from xml file

I have an xml file which I need to modify and write it back to an outputfile.
The problem is that the result outputfile contains an extra attribute 'standalone' in the root declartion which does not exist in the original inputfile.
Is there any way how I can prevent from XmlDocument adding this attribute ?
The code I have tried:
//read input xml
XmlDocument xDoc = new XmlDocument();
xDoc.Load(originalFile);
//do some stuff
//....
//write back to output
using(XmlTextWriter xml2 = new XmlTextWriter(outputFile, Encoding.UTF8) { Formatting = Formatting.Indented })
{
xDoc.CreateXmlDeclaration("1.0", null, "");
xDoc.Save(xml2);
}
inputfile contains this:
<?xml version="1.0" encoding="UTF-8" ?>
...
output.xml contains this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
...
The standalone parameter should be null or String.empty.
xDoc.CreateXmlDeclaration("1.0", null, null);
Also CreateXmlDecleration just creates a declaration object. You still need to add it to the document, like this:
XmlDeclaration xDecl = xDoc.CreateXmlDeclaration("1.0", null, null);
if (xDoc.FirstChild.NodeType == XmlNodeType.XmlDeclaration)
xDoc.ReplaceChild(xDecl, xDoc.FirstChild);
else
xDoc.InsertBefore(xDecl, xDoc.DocumentElement);

Categories

Resources