XMLDocument Load(XmlReader) vs Load(Stream) - c#

I am using XMLDocument Load function with input arguments as stream xml data. I see a violation for doing that CA3075. For string data, it is suggested to create XmlReader object and pass it to XMLDocument Load function with XMLResolver value set to null in arguments.
System.IO.StringReader sreader = new System.IO.StringReader(xml);
XmlReader reader = XmlReader.Create(sreader, new XmlReaderSettings() { XmlResolver = null });
doc.Load(reader);
ref : https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca3075#solution-3
I wanted to understand what difference does it make of using XMLReader vs stream as arguments?

Related

XML validation with XSD file

I try to validate my xml structure, using an xml schema.
This code sample is given here : https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldocument.validate?view=net-5.0
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);
XmlDocument document = new XmlDocument();
document.Load(reader);
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
// the following call to Validate succeeds.
document.Validate(eventHandler);
// add a node so that the document is no longer valid
XPathNavigator navigator = document.CreateNavigator();
navigator.MoveToFollowing("price", "http://www.contoso.com/books");
XmlWriter writer = navigator.InsertAfter();
writer.WriteStartElement("anotherNode", "http://www.contoso.com/books");
writer.WriteEndElement();
writer.Close();
// the document will now fail to successfully validate
document.Validate(eventHandler);
Problem is that when I'm using a non valide xml document, I already have an exception of type System.Xml.Schema.XmlSchemaValidationException on line :
XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);
Does this mean you dont need to use this Validate(eventHandler) method with C# 6 anymore ? Or will it take care of few specific validation problems ?

"DTD is prohibited" exception when transforming XML file

I've created a custom HTMLHelper which is supposed to render parsed XML. The method takes the XML and the path to an XSL file and should return HTML.
When I access the page, I get the error
XmlException: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.
As you can see in my code below, I'm setting DtdProcessing toParse in the XmlReaderSettings (as the exception suggests), which I thought would resolve the issue. On closer inspection, the exception is occurring at the line:
transformObj.Load(xsltPath);
But I can't see how I can pass XmlReaderSettings to that method so as to set the DtdProcessing property. The only overloads of XslCompiledTransform.Load which accept a settings object expect a XsltSettings object, which doesn't have a DtdProcessing property.
The full method is as follows:
public static IHtmlContent RenderXml(this IHtmlHelper htmlHelper, string xml, string xsltPath)
{
XsltArgumentList args = new XsltArgumentList();
// Create XslCompiledTransform object to load and compile XSLT file.
XslCompiledTransform transformObj = new XslCompiledTransform();
transformObj.Load(xsltPath);
// Create XMLReaderSetting object to assign DtdProcessing, Validation type
XmlReaderSettings xmlSettings = new XmlReaderSettings();
xmlSettings.DtdProcessing = DtdProcessing.Parse;
xmlSettings.MaxCharactersFromEntities = 1024; // Prevent DoS attacks
xmlSettings.ValidationType = ValidationType.DTD;
// Create XMLReader object to Transform xml value with XSLT setting
XmlReader reader = XmlReader.Create(new StringReader(xml), xmlSettings);
using (reader)
{
StringWriter writer = new StringWriter();
transformObj.Transform(reader, args, writer);
// Generate HTML string from StringWriter
HtmlString htmlString = new HtmlString(writer.ToString());
return htmlString;
}
}
And in my view I'm using:
#Html.RenderXml(ViewBag.XML as string, ViewBag.XSL as string);
I've reviewed the advice in the answers to this question but as far as I can tell I've already taken the steps suggested. The accepted answer to this MSDN question seems to hint at an answer but I haven't been able to work out how to make use of it.
If the XSLT uses or references a DTD, pass an XmlReader with the necessary XmlReaderSettings to the Load method, i.e. use the overload https://learn.microsoft.com/en-us/dotnet/api/system.xml.xsl.xslcompiledtransform.load?view=netframework-4.8#System_Xml_Xsl_XslCompiledTransform_Load_System_Xml_XmlReader_ with
using (XmlReader xsltReader = XmlReader.Create(xsltPath, new XmlReaderSettings() { DtdProcessing = DtdProcessing.Parse }))
{
transformObj.Load(xsltReader);
}

How to pass and get the string based xml data in xslt transform using C#?

I want to convert one xml file into another xml file using xslt.here, i can able to pass the input document to the XPathDocument and also save the output file in disk by passing outfile into XmlTextWriter.
But now my problem is... i have my input is in string format and i also want output as a string.Instead of passing the location of the input file, i want to pass string that contains the xml data.
so i have to pass string object into xpathDoccument in someway and also get the resultant xml file as a string.Instead of save the output as a file,i want output as a string.
XPathDocument xpathDoc = new XPathDocument("C:\\InputXml.xml");
XslCompiledTransform xslt = new XslCompiledTransform();
string xsltFile = "C:\\conversion.xslt";
xslt.Load(xsltFile);
string outputFile = "C:\\myHtml.html";
XmlTextWriter writer = new XmlTextWriter(outputFile, null);
xslt.Transform(xpathDoc, null, writer);
writer.Close();
Please guide me to get out of this issue...
XPathDocument accepts TextReader. You can give a stream as new XPathDocument(new StringReader(xmlstring)). Similarly XmlTextWriter accepts TextWriter. So you can pass a StringWriter.
--edit--
var sw = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(sw);
xslt.Transform(xpathDoc, null, writer);
var str= sw.ToString();
Try this,
XslTransform xTrans = new XslTransform();
xTrans.Load(nodeXsltPath); //xsl file path
XmlDocument input= new XmlDocument();
XmlDocument output= new XmlDocument();
input.LoadXml(xmlString); /* Xml string to be loaaded */
output.Load(xTrans.Transform(input,null,new XmlUrlResolver()));
output.Save(filePathtoSave);

XslCompiledTransform and Serialization

I am trying to implement some functions that will convert one object to another with XslCompiledTransform.
I found some implementations for Serializing an object to XML string and DeSerialize the XML string to an object.
Another function does the XslCompiledTransform from object1 to obejbct2.
To generate the XSLT file i used the Altova MapForce, just loaded the XML of the serialized objects and mapped some attributes.
Now for the problems:
first I noticed that the XslCompiledTransform doesn't work with XSLT version 2.0. is there any newer functions that do work with XSLT 2.0? maybe some settings?
secondly I get an exception when trying to DeSerialize the XML to an object:
"There was an error deserializing the object of type myObject Input string was not in a correct format."
I don't understand where is the problem.
Does anybody have a sample code that does such a thing? all I find in google are Transformations of HTML code and not objects.
Here are the functions:
private static string runXSLT(string xsltFile, string inputXML)
{
XmlDocument XmlDoc = new XmlDocument();
// Load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform(true);
xslt.Load(xsltFile);
StringReader StrReader = new StringReader(inputXML);
XmlTextReader XmlReader = new XmlTextReader(StrReader);
//Create an XmlTextWriter which outputs to memory stream
Stream stream = new MemoryStream();
XmlWriter writer = new XmlTextWriter(stream, Encoding.UTF8);
// Execute the transform and output the results to a file.
xslt.Transform(XmlReader, writer);
stream.Position = 0;
XmlDoc.Load(stream);
return XmlDoc.InnerXml;
}
public static string SerializeAnObject(object AnObject)
{
XmlDocument XmlDoc = new XmlDocument();
DataContractSerializer xmlDataContractSerializer = new DataContractSerializer(AnObject.GetType());
MemoryStream MemStream = new MemoryStream();
try
{
xmlDataContractSerializer.WriteObject(MemStream, AnObject);
MemStream.Position = 0;
XmlDoc.Load(MemStream);
return XmlDoc.InnerXml;
}
finally
{
MemStream.Close();
}
}
public static Object DeSerializeAnObject(string XmlOfAnObject, Type ObjectType)
{
StringReader StrReader = new StringReader(XmlOfAnObject);
DataContractSerializer xmlDataContractSerializer = new DataContractSerializer(ObjectType);
XmlTextReader XmlReader = new XmlTextReader(StrReader);
try
{
Object AnObject = xmlDataContractSerializer.ReadObject(XmlReader);
return AnObject;
}
finally
{
XmlReader.Close();
StrReader.Close();
}
}
Thanks allot,
Omri.
XslCompiledTransform does not support XSLT 2.0. In fact, XSLT 2.0 is not supported within the .NET Framework at all (you could try the Saxon version for .NET, but be aware that this is just the Java version running inside IKVM).
From your description I did not understand why you are taking the detour via XML to convert one object into another. Why don't you simply provide a constructor in your target object that takes your input object as a paramater? Then you can code all the mapping inside that constructor. This is not onlyby far more efficient than serializing, transforming and deserializing your objects you will also get the type safety of C#.

Creating an XML Element object from an XML Writer in C#

I'm writing a Windows service in C#. I've got an XmlWriter which is contains the output of an XSLT transformation. I need to get the XML into an XMLElement object to pass to a web service.
What is the best way to do this?
You do not need an intermediate string, you can create an XmlWriter that writes directly into an XmlNode:
XmlDocument doc = new XmlDocument();
using (XmlWriter xw = doc.CreateNavigator().AppendChild()) {
// Write to `xw` here.
// Nodes written to `xw` will not appear in the document
// until `xw` is closed/disposed.
}
and pass xw as the output of the transform.
NB. Some parts of the xsl:output will be ignored (e.g. encoding) because the XmlDocument will use its own settings.
Well, an XmlWriter doesn't contain the output; typically, you have a backing object (maybe a StringBuilder or MemoryStream) that is the dumping place. In this case, StringBuilder is probably the most efficient... perhaps something like:
StringBuilder sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb))
{
// TODO write to writer via xslt
}
string xml = sb.ToString();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlElement el = doc.DocumentElement;
If you provide a writer, you provide a repository where an output generator is transferring data, thus the replay of Richard is good, you don't really need a string builder to send data from a reader to an XmlDocument!

Categories

Resources