I'm trying to generate XML from another XML using a XslTransform. I get both files (source XML and XSL transformation file) as string content, so I'm trying to pass the XSL file to XslTransform.Load() method as XmlReader. Now the XmlReader has to be created form a source string containing XSL file, so i try doing it like this:
MemoryStream memStream = new MemoryStream();
byte[] data = Encoding.Default.GetBytes(transformation.XsltContent);
memStream.Write(data, 0, data.Length);
memStream.Position = 0;
XmlReader reader = XmlReader.Create(memStream);
and also tried using a StringReader:
XmlReader reader = XmlReader.Create(new StringReader(transformation.XsltContent));
Unfortunately, bot methods don't seems to work, the input seems to be ok, I even tried creating some basic one-element XML to pass, won't work either - reader contains {None}.
Could someone point out what seems to be the problem here?
XmlReader xmlReader = XmlReader.Create(new StringReader(YourStringValue));
The StringReader -> XmlReader approach is fine, you should stick to it. The reader reports none because it hasn't been read yet. Try calling Read() on it to see what happens then. The transformation will also call read on it.
Related
I want to create in an app - coded with C# - a copy of the actual element of a XMLReader object by using a XMLDocument instance.
The purpose is to get a copy of the actual reader element, so i can read the inner XML from the actual XML element without moving in the original reader.
When i try to load the reader into the XMLDocument i get the error "The document already has a 'DocumentElement' node.".
Any help would be appreciated.
XmlDocument xmlDocument = new XmlDocument();
MemoryStream streamFromReader = new MemoryStream();
xmlDocument.Load(reader); //Here i get the error
xmlDocument.Save(streamFromReader);
streamFromReader.Position = 0;
XmlReader copyReader = XmlReader.Create(streamFromReader);
sb.Append(copyReader.ReadInnerXml());
copyReader.Close();
The problem is that the reader is already positioned somewhere in the middle of the XML file, e.g.:
<Parent> <---- Position of the reader
<Child></Child>
<Child></Child>
</Parent>
<Parent>
<Child></Child>
<Child></Child>
</Parent>
The Load method starts to read the current node and also reads the siblings of the node. This leads to an invalid XML structure, because the document can only have one root element. The docs describe this behavior in the remarks section.
As for the original purpose of the code, I understand you want to perform a Peek (check the contents without advancing the reader) on the XmlReader. There are limited options to achieve this because an XmlReader operates forward-only. The answers to this question describe some options on how to read from an XmlReader without advancing it.
The answer of Markus helped me to get to the solution.
When the XMLReader is getting to an element which has subitems, i must get first the actual position within the file using the interface IXmlLineInfo.
IXmlLineInfo lineInfo = (IXmlLineInfo)reader;
int lineNumber = lineInfo.LineNumber;
int linePosition = lineInfo.LinePosition;
Then i create an instance of XmlTextReader, which reads the file to that position.
When the reminded position was arrived, the XmlTextReader contains the element and i can get the inner XML from it.
Stream stream = new MemoryStream(myFile.FileBytes);
XmlTextReader textReader = new XmlTextReader(stream);
while (textReader.LineNumber < lineNumber)
{
textReader.Read();
}
string innerXml = textReader.ReadInnerXml());
textReader.Close();
I'm using an external API to receive xml and serializing this to an object but I want a way to be able to keep the original xml used to serialize for debugging and auditing.
Here's a sample of how I'm serializing:
XmlReader reader = this.Execute(url);
return Read<Property>(reader, "property");
Extract of Execute() routine:
StringBuilder sb = new StringBuilder();
Stream s = response.GetResponseStream();
XmlReader reader = XmlReader.Create(s);
return reader;
Read() simply wraps up the native xml serialization:
private T Read<T>(XmlReader reader, string rootElement)
{
XmlRootAttribute root = new XmlRootAttribute();
root.ElementName = rootElement;
root.IsNullable = true;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), root);
object result = xmlSerializer.Deserialize(reader);
return (T)result;
}
I've had a look around at it appears once you've used the reader, you can't use it again (forward only reading stream?). Without trying to change to much, how can I extract the contents of the reader as xml while still benefiting from the built in serialization with the reader?
What would be nice is to adjust Read with an out param:
private T Read<T>(XmlReader reader, string rootElement, out string sourceXml);
You did not share the code for this.Execute(url), but presumably you build a reader from a stream. First write that stream to a string, then use it somewhere. If the stream is not seekable, dispose it and create a new stream from it.
Also, note that XmlSerializer can take a stream instead of a reader, so you could never bother with the reader and just pass streams among your methods.
Use fiddler.
Fiddler is a Web Debugging Proxy which logs all HTTP(S) traffic between your computer and the Internet. Fiddler allows you to inspect traffic, set breakpoints, and "fiddle" with incoming or outgoing data. Fiddler includes a powerful event-based scripting subsystem, and can be extended using any .NET language.
Working with C# Visual Studio 2008, MVC1.
I'm creating an xml file by fetching one from a WebService and adding some nodes to it. Now I wanted to deserialize it to a class which is the model used to strongtyped the View.
First of all, I'm facing problems to achieve that without storing the xml in the filesystem cause I don't know how this serialize and deserialize work. I guess there's a way and it's a matter of time.
But, searching for the previous in the web I came accross LINQ to XML and now I doubt whether is better to use it.
The xml would be formed by some clients details, and basically I will use all of them.
Any hint?
Thanks!!
You can save a XElement to and from a MemoryStream (no need to save it to a file stream)
MemoryStream ms = new MemoryStream();
XmlWriter xw = XmlWriter.Create(ms);
document.Save(xw);
xw.Flush();
Then if you reset the position back to 0 you can deserialize it using the DataContractSerializer.
ms.Position = 0;
DataContractSerializer serializer = new DataContractSerializer(typeof(Model));
Model model = (model) serializer.ReadObject(ms);
There are other options for how serialization works, so if this is not what you have, let me know what you are using and I will help.
try this:
XmlSerializer xmls = new XmlSerializer(typeof(XElement));
FileStream FStream;
try
{
FStream = new FileStream(doctorsPath, FileMode.Open);
_Doctors = (XElement)xmls.Deserialize(FStream); FStream.Close();
FStream = new FileStream(patientsPath, FileMode.Open);
_Patients = (XElement)xmls.Deserialize(FStream)
FStream.Close();
FStream = new FileStream(treatmentsPath, FileMode.Open);
_Treatments = (XElement)xmls.Deserialize(FStream);
FStream.Close();
}
catch
{ }
This will load all of the XML files into our XElement variables. The try – catch block is a form of exception handling that ensures that if one of the functions in the try block throws an exception, the program will jump to the catch section where nothing will happen. When working with files, especially reading files, it is a good idea to work with try – catch.
LINQ to XML is an excellent feature. You can always rely on that. You don't need to write or read or data from file. You can specify either string or stream to the XDocument
There are enough ways to load an XML element to the XDocument object. See the appropriate Load functions. Once you load the content, you can easily add/remove the elements and later you can save to disk if you want.
I'm trying to find a way of indenting a HTML file, I've been using XMLDocument and just using a XmlTextWriter.
However I am unable to format it correctly for HTML documents because it checks the doctype and tries to download it.
Is there a "dumb" indenting mechanism that doesnt validate or check the document and does a best effort indentation? The files are 4-10Mb in size and they are autogenerated, we have to handle it internal - its fine, the user can wait, I just want to avoid forking to a new process etc.
Here's my code for reference
using (MemoryStream ms = new MemoryStream())
using (XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.Unicode))
{
XmlDocument doc = new XmlDocument();
// LoadSettings the unformatted XML text string into an instance
// of the XML Document Object Model (DOM)
doc.LoadXml(content);
// Set the formatting property of the XML Text Writer to indented
// the text writer is where the indenting will be performed
xtw.Formatting = Formatting.Indented;
// write dom xml to the xmltextwriter
doc.WriteContentTo(xtw);
// Flush the contents of the text writer
// to the memory stream, which is simply a memory file
xtw.Flush();
// set to start of the memory stream (file)
ms.Seek(0, SeekOrigin.Begin);
// create a reader to read the contents of
// the memory stream (file)
using (StreamReader sr = new StreamReader(ms))
return sr.ReadToEnd();
}
Essentially, right now I use a MemoryStream, XmlTextWriter and XmlDocument, once indented I read it back from the MemoryStream and return it as a string. Failures happen for XHTML documents and some HTML 4 documents because its trying to grab the dtds. I tried setting XmlResolver as null but to no avail :(
Without access to the specific X[H]TML causing the problems, it's hard to know if this will work, but have you tried using XDocument instead?
XDocument xdoc = XDocument.Parse(xml);
string formatted = xdoc.ToString();
Its been a while since i've needed to do this so i was looking at the old school methods of writing XMLDocument from code down to a File.
In my application i am writing alot to an XMLdocument with new elements and values and periodically saving it down to disc and also reading from the file and depending on the data i am doing things.
I am using methods like File.Exists(...) _xmldoc.LoadFile(..) etc...
Im wondering probably now a days there are better methods for this with regards
Parsing the XML
Checking its format for saving down
rather then the data being saved down being treated as text but as XML
maybe what i am doing is fine but its been a while and wondered if there are other methods :)
thanks
Well there's LINQ to XML which is a really nice XML API introduced in .NET 3.5. I don't think the existing XMLDocument API has changed much, beyond some nicer ways of creating XmlReaders and XmlWriters (XmlReader.Create/XmlWriter.Create).
I'm not sure what you really mean by your second and third bullets though. What exactly are you doing in code which feels awkward?
Have you looked at the Save method of your XmlDocument? It will save whatever is in your XmlDocument as a valid formatted file.
If your program is able to use the XmlDocument class, the XmlDocument class will be able to save your file. You won't need to worry about validating before saving, and you can give it whatever file extension you want. As to your third point... an XML file is really just a text file. It won't matter how the OS sees it.
I was a big fan of XmlDocument due to its facility to use but recently I got a huge memory problem with that class so I started to use XmlReader and XmlWriter.
XmlReader can be a little bit tricky to use if your Xml file is complex because you read the Xml file sequentially. In that case, the method ReadSubTree of XmlReader can be very useful because this method returns only the xml tree under the current node so you send the new xmlreader to a function to parse the subnode content and once it is done, you continue to the next node.
XmlReader Example:
string xmlcontent = "<BigXml/>";
using(StringReader strContent = new StringReader(xmlcontent))
{
using (XmlReader reader = XmlReader.Create(strContent))
{
while (reader.Read())
{
if (reader.Name == "SomeName" && reader.NodeType == XmlNodeType.Element)
{
//Send the XmlReader created by ReadSubTree to a function to read it.
ReadSubContentOfSomeName(reader.ReadSubtree());
}
}
}
}
XmlWriter Example:
StringBuilder builder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(builder))
{
writer.WriteStartDocument();
writer.WriteStartElement("BigXml");
writer.WriteAttributeString("someAttribute", "42");
writer.WriteString("Some Inner Text");
//Write nodes under BigXml
writer.WriteStartElement("SomeName");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
}