combining xmls files in a loop and removing the nodes not needed - c#

Im trying to combine multiple xml files through a loops.
I put the first XML in a string then add the next one to the same string.
I do remove the xml declaration first before i add using
XmlDocument doc = new XmlDocument();
doc.LoadXml(currentdaydata);
var declarations = doc.ChildNodes.OfType<XmlNode>()
.Where(x => x.NodeType == XmlNodeType.XmlDeclaration)
.ToList();
declarations.ForEach(x => doc.RemoveChild(x));
Each xml response is in the following format like the below but i cant seem to remove the root element.
xml 1 = <response><movie>....<movie></response>
xml 2 = <response><movie>....<movie></response>
xml 3 = <response><movie>....<movie></response>
outputdata += xml(i);
outputdata =
<response><movie>....<movie></response><response><movie>....<movie></response><response><movie>....<movie></response>
I tried to remove it using a string replace but no luck
outputdata.Replace("</response><response>", "");
....

Don't try to manipulate XML as a string: sooner or later you'll get some input you can't handle, or you'll produce some output that your customers can't handle, and the questions to SO that result from this will keep us all busy for years. Always use a real XML parser, even for the simplest of jobs.
If you download an XQuery processor such as Saxon then you can do this as a one-liner:
<response>{$docs/response/*}</response>
where $docs is supplied as the sequence of parsed input documents,

Related

count number of "elements" in an XML tag using c#

I'm using C# in reading an XML file and counting how many "elements" there are in an XML tag, like this for example...
<Languages>English, Deutsche, Francais</Languages>
there are 3 "elements" inside the Languages tag: English, Deutsche, and Francais . I need to know how to count them and return the value of how much elements there are. The contents of the tag have the possibility of changing over time, because the XML file has to expand/accommodate additional languages (whenever needed).
IF this is not possible, please do suggest workarounds for the problem. Thank you.
EDIT: I haven't come up with the code to read the XML file, but I'm also interested in learning how to.
EDIT 2: revisions made to question
string xml = #"<Languages>English, Deutsche, Francais</Languages>";
var doc = XDocument.Parse(xml);
string languages = doc.Elements("Languages").FirstOrDefault().Value;
int count = languages.Split(',').Count();
In response to your edits which indicate that you're not simply trying to pull out comma separated strings from an XML element, then your approach to storing the XML in the first place is incorrect. As another poster commented, it should be:
<Languages>
<Language>English</Language>
<Language>Deutsche</Language>
<Language>Francais</Language>
</Languages>
Then, to get the count of languages:
string xml = #"<Languages>
<Language>English</Language>
<Language>Deutsche</Language>
<Language>Francais</Language>
</Languages>";
var doc = XDocument.Parse(xml);
int count = doc.Element("Languages").Elements().Count();
First, an "ideal" solution: do not put more than one piece of information in a single tag. Rather, put each language in its own tag, like this:
<Languages>
<Language>English</Language>
<Language>Deutsche</Language>
<Language>Francais</Language>
</Languages>
If this is not possible, retrieve the content of the tag with multiple languages, split using allLanguages.Split(',', ' '), and obtain the count by checking the length of the resultant array.
Ok, but just to be clear, an XML Element has a very specific meaning. In fact, the entire codeblock you have is an XML Element.
XElement xElm = new XElement("Languages", "English, Deutsche, Francais");
string[] elements = xElm.Value.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

"An error occurred while parsing EntityName" after grabbing content from valid XML

I am reading an XML string with XDocument
XmlReader reader = XmlReader.Create(new StringReader(xmltext));
reader.Read();
XDocument xdoc = XDocument.Load(reader);
Then I grab the content of some tags and put them within tags in a different string.
When I try to Load this string in the same way I did with the first, I get an error "An error occurred while parsing EntityName. Line 1, position 344.".
I think it should be parsed correctly since it has beem parsed before so I guess I am missing something here.
I am reading and copying the content of the first XML with (string)i.Element("field").
I am using .net 4
When I grab the content of the xml that I want to use for building another Xml string I use (string)i.Element("field") and this is converting my Xml into string. My next Xml Parsing does not recognize it as an Element anymore so I solved the problem by not using (string) before I read my element, just i.Element("field") and this works.
It sounds like you've got something like this:
<OriginalDocument>
<Foo>A & B</Foo>
</OriginalDocument>
That A & B represents the text A & B. So when you grab the text from the element, you'll get the string "A & B". If you then use that to build a new element like this:
string foo = "<Foo>" + fooText + "</Foo>";
then you'll end up with invalid XML like this:
<Foo>A & B</Foo>
Basically, you shouldn't be constructing XML in text form. It's not clear what you're really trying to achieve, but you can copy an element from one place to another pretty easily in XElement form; you shouldn't need to build a string and then reparse it.
So after spending hours on this issue:
it turns out that if you have an ampersand symbol ("&") or any other XML escape characters within your xml string, it will always fail will you try read the XML.
TO solve this, replace the special characters with their escaped string format
YourXmlString = YourXmlString.Replace("'", "&apos;").Replace("\"", """).Replace(">", ">").Replace("<", "<").Replace("&", "&");

Grab All XML Elements of a Specific Type: Even nested elements

I am parsing an XML document in C# ASP.NET. Is there a way/function that I don't know of to get all the elements of the tag "course"?
The format of the XML is like so:
<a>
<g1>
<course></course>
<g9>
<course></course>
... more course elements
</g9>
<course></course>
<g2>
<g3>
<course></course>
...
</g3>
</g2>
</g1>
</a>
When I do the following code I get back no "course" elements, is there a simple function that can grab all these elements in one go?
XmlDocument xdoc = new XmlDocument();
xdoc.Load("http://kjkjkj.com");
XmlNodeList list = xdoc.DocumentElement.SelectNodes("course");
// if I debug: list.count = 0 but if I look at xdoc.DocumentElement.outerXml
// its the correct XML so I did parse the file & get XML contents.
// Is there any C# equivalent of document.getElementsByTagName("course"); ???
You were close:
XmlNodeList list = xdoc.DocumentElement.SelectNodes("//course");
Prefixing with // will grab all the nodes in the document named course, no matter where they are.
As an alternative you should consider parsing your XML with Linq to Xml which integrates nicely with Linq to objects. The equivalent syntax for the same there is
var courses = xdoc.Descendants("course");

c# linq to xml

I have an xml string that I wish to traverse using LINQ to XML (I have never used this, so wish to learn). However when I try to use
XDocument xDoc = XDocument.Load(adminUsersXML);
var users = from result in xDoc.Descendants("Result")
select new
{
test = result.Element("USER_ID").Value
};
I get an error message saying illegal characters in path. reading up on it, it's because I cannot pass a standard string in this way. Is there a way to use XML LINQ qith a standard string?
Thanks.
My guess is that adminUsersXML is the XML itself rather than a path to a file containing XML. If that's the case, just use:
XDocument doc = XDocument.Parse(adminUsersXML);
As said in MSDN, you must use the Parse function to create a XDocument from a string.
I think adminUserXML is not a file but a string containing xml, which should be parsed to convert to XDocument with XDocument.Parse(adminUserXML)

Writing XML in C# - 'Token StartElement in state Epilog would result in an invalid XML document' error

I'm trying to write to an XML document, taking data from an ArrayList of lists
for (int i = 0; i < 15; i++)
{
string headname = (headers[0] as List<string>)[i];
headname.Replace("&", "&");
headname.Replace("<", "<");
headname.Replace(">", ">");
headname.Replace("\"", """);
headname.Replace("'", "&apos;");
textWriter.WriteStartElement("MetadataName", "");
textWriter.WriteString(headname);
textWriter.WriteEndElement();
The problem I'm having is that after it goes through the for loop once, i get a 'Token StartElement in state Epilog would result in an invalid XML document' error on the line with WriteStartElement, and I've tried looking up how to fix it and have not really had any breakthroughs. Thanks.
EDITED for update.
An XML document will have a root element ie one that includes all other elements. You don't have one
Your doc is like
<MetadataName><header0/><header1/></MetadataName>
<MetadataName><header0/><header1/></MetadataName>
An XML doc is like
<root>
<MetadataName><header0/><header1/></MetadataName>
<MetadataName><header0/><header1/></MetadataName>
</root>
You need to WriteStartElement and WriteEndElement around your loop
Your problem is here:
textWriter.WriteStartElement("Metadata Name", "");
An element name cannot contain spaces. Try this:
textWriter.WriteStartElement("MetadataName", "");
I am assuming that the data in your headers array is well formed for XML (for example, all & are escaped to & etc...).
Additionally, as Mark notes in his answer, you need to make sure the XML is rooted - that is, that there is a root element in which you put your MetadataName elements.
Read about well formed XML and what that means - you need to make sure your document is well formed, as you build it up.

Categories