Parsing XML Using C# in uwp Xaml - c#

How do you get the data from description in the tag something: <something description = "something else"> </something> using c# in uwp.

Here is the test code to show how to get the XML node attribute value:
private void GetContent()
{
string xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><body><content title =\"XML File!\"></content></body>";
var doc = new XmlDocument();
doc.LoadXml(xml);
var tags=doc.GetElementsByTagName("content");
if (tags.Count > 0)
{
var firstContent = tags.First();
string result = firstContent.Attributes.GetNamedItem("title").InnerText;
}
}
Tips
In UWP, loading an XmlDocument via a path is not recommended. It is best to get the XML file first, read all the text, and load the XmlDocument via text.
The XmlDocument prefix namespace is Windows.Data.Xml.Dom, NOT System.Xml
Best regards.

Related

Using XDocument to read the root element from XML using C# is not showing the root element

I am new to C# programming and trying to update the XML file using C#. Here when I am trying to get the root element using XDocument it is showing the complete script in the file.
Below is my code explanation:
I am having the below function and it is reading the file path from the command line arguments.
private XDocument doc;
public void Update(string filepath)
{
string filename = Path.GetFileName(filepath);
doc = xDocument.Load(filepath);
XElement rootelement = doc.Root;
}
Into the filepath variable, we are taking the path "E:\BuilderTest\COMMON.wxs"
Then we are loading the file using XDocument.
But when we are trying to get the rootelement from the file, it is not showing the root element. Instead, it is showing the complete data in the file.
But when I am using XmlDocument() instead of XDocument() I am able to see only the root element.
Below is the code using XmlDocument():
private XmlDocument doc;
public void Update(string filepath)
{
string filename = Path.GetFileName(filepath);
doc = new XmlDocument();
doc.Load(filepath);
XmlElement rootelement = doc.DocumentElement;
}
Please help me by providing your valuable inputs on this.
XDocument and XmlDocument are different class structure to follow as per requirement.
XDocument will work like below
XDocument doc;
doc = XDocument.Load(filepath);
XElement root = doc.Root;
Root, Descendants, Elements are the operations provided in XDocument. For every node its gives XElement
In your case you should use doc.Root to find the element, then use .Value to get its value
XElement comes with System.Xml.Linq. It is derived from XNode.
It gives you serialized information of every node one by one.
On the other hand XMLDocument will work like below
XmlDocument doc;
doc = new XmlDocument();
doc.Load(filepath);
XmlElement rootelement = doc.DocumentElement;
XmlElement comes with System.Xml. It is derived from XmlNode which is again derived from IEnumerable.
It gives you information in a Enumerable which you can easily parse.

C# Find and replace data inside XML tag

Xml File :
<?xml version="1.0" encoding="iso-8859-1"?>
<ResDoc>
<Summary>
My name is Magesh
</Summary>
</ResDoc>
How to find the data "Magesh" inside Summary tag and replace it as "GivenName".
A c# code to load XML file, find and replace.
I have tried to loading xml file using XMLDocument, find and replace. But it is not expected.
xdoc = new XmlDocument {PreserveWhitespace = true};
xdoc.LoadXml(taggedresume);
string Name1 = "Magesh";
foreach (XmlNode var in xdoc.SelectSingleNode("//ResDoc/summary"))
{
var.InnerXml.Replace(Name1, "GivenName");
}
static void Main(string[] args)
{
string xml = #"<?xml version=""1.0"" encoding=""iso-8859-1""?>
<ResDoc>
<Summary>
My name is Magesh
</Summary>
</ResDoc>";
XDocument doc = XDocument.Parse(xml);
var element = doc.Element("ResDoc").Element("Summary");
element.Value = element.Value.Replace("Magesh", "YourName");
Console.WriteLine(element.Value);
Console.ReadKey();
}
Here an example, next time try something by yourself first. You need to have reference to System.Xml.Linq;

Writing in xml does not keep the formatting?

I have this string :
<test>I am a test</test>
But when I write it in my xml file, and open it, I have this :
<test>I am a test</test>
I don't know how to use the good formatting. I tried HttpUtility.HtmlDecode, but it does not solve my problem.
Do you have an idea on this ?
Edit : Sorry for not having posted my code before, I thought my problem was really really trivial. Here is a sample I just wrote that resumes the situation (I'm not at work anymore so I don't have the original code) :
XmlDocument xmlDoc = new XmlDocument();
doc.LoadXml("<root>" +
"<test>I am a test</test>" +
"</root>");
string content = xmlDoc.DocumentElement.FirstChild.InnerXml;
XDocument saveFile = new XDocument();
saveFile = new XDocument(new XElement("settings", content));
saveFile.Save("myFile.xml");
I just want my xml file content looks like my original string,
so in my case the file would normally contain :
<settings>
<root>
<test>I am a test</test>
</root>
</settings>
Right ? But instead, I have something like :
<settings><root><test>I am a test</test></root>
</settings>
You can do something along the lines of Converting XDocument to XmlDocument and vice versa to convert the root element of your XmlDocument to an XElement and then add it to your XDocument:
public static class XmlDocumentExtensions
{
public static XElement ToXElement(this XmlDocument xmlDocument)
{
if (xmlDocument == null)
throw new ArgumentNullException("xmlDocument");
if (xmlDocument.DocumentElement == null)
return null;
using (var nodeReader = new XmlNodeReader(xmlDocument.DocumentElement))
{
return XElement.Load(nodeReader);
}
}
}
And then use as follows:
// Get legacy XmlDocument
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<root>" +
"<test>I am a test</test>" +
"</root>");
// Add its root element to the XDocument
XDocument saveFile = new XDocument(
new XElement("settings", xmlDoc.ToXElement()));
// Save
Debug.WriteLine(saveFile.ToString());
And the output is:
<settings>
<root>
<test>I am a test</test>
</root>
</settings>
Note this avoids the overhead of converting the XmlDocument to an XML string and re-parsing it from scratch.

Calling method from catch method doesn't work

I'm trying to call a method from a catch block but the xmlnode inside the method doesn't seem to work. I'm getting a null. If I call the same method from the try block it works.
var doc = new XmlDocument();
try
{
doc.Load(f.FullPath);
// do some work
}
catch (Exception e)
{
if (e is XMLException)
{
checkXML(ref doc);
}
public void checkXML(ref XmlDocument doc)
{
XmlNode xn = doc.SelectSingleNode("/BroadcastMonitor/Current");
xn["name1"].InnerText = SecurityElement.Escape(xn["name1"].InnerText);
xn["name2"].InnerText = SecurityElement.Escape(xn["name2"].InnerText); ;
}
Now when the catch block calls method 'checkXML', i get xn as null. But if I execute the same from the 'try' block just to check, 'xn' has a value. 'doc' too has a value regardless of when called try or from catch block.
Why is this happening? Please help me understand.
EDIT
<BroadcastMonitor>
<updated>2014-10-17T07:56:30</updated>
<Name>TESTING</Name>
<Current>
<artistName>اصاله& نصرى</artistName>
<albumName>شخصيه عنيده</albumName>
<CategoryName>ARABIC & SONGS</CategoryName>
</Current>
</BroadcastMonitor>
Thank you.
Your xml contains an & character which is not a 'valid' xml character and must be escaped.
<CategoryName>ARABIC & SONGS</CategoryName>
So it's causing your Load() method to throw the exception.
What you should do is escape all the invalid characters in your xml string before passing them on to an xml parser like so
yourXmlString = XmlConvert.EncodeName(yourXmlString);
You can then pass the yourXmlString on to the parser like so
var xDoc = XDocument.Parse(yourXmlString);
or if you don't want to or can't use the XDocument class you will need to make sure you save the xml encoded so that the Load() method of the XmlDocument class will be reading a file that is properly encoded.
Note that XmlDocument and XDocument classes are not the same thing and have some significant differences. Method Parse(), if I remember correctly, is one of the advantages that XDocument has over XmlDocument.
EDIT :
You can read the xml file into a string using the File class
var yourXmlString = File.ReadAllText(filePath);
XmlDocument is a reference type... no need to pass it with ref.
And my guess is that its failing to load in the first place so doc is really null
It looks like this document is missing its xml declaration tag.
try:
XmlDocument doc = new XmlDocument;
using(StreamReader reader = new StreamReader(f.FullPath))
{
doc.LoadXml(reader.ReadToEnd());
}
You can use System.IO.File.ReadAllText() to get all text from file into a string variable :
string invalidXml = System.IO.File.ReadAllText(f.FullPath);
For this particular XML, you can simply replace & with it's encoded version & to make a valid XML string :
string validXml = invalidXml.Replace("&", "&");
doc.LoadXml(validXml);
.....
Related question for reference : Reading XML with an "&" into C# XMLDocument Object
This would be my solution:
private static Regex InnerValues = new Regex(#"(?<=<(.*?>)).*?(?=</\1)",RegexOptions.Compiled);
private static XmlDocument LoadInvalidDocument(string path)
{
XmlDocument result = new XmlDocument();
string content = File.ReadAllText(path);
var matches = InnerValues.Matches(content);
foreach (Match match in matches)
{
content = content.Replace(match.Value, HttpUtility.HtmlEncode(match.Value));
}
result.LoadXml(content);
return result;
}

Select xml file part with xpath and xdocument - C#/Win8

I am building a Windows 8 app, and I need to extract the whole XML node and its children as string from a large xml document, and the method that does that so far looks like this:
public string GetNodeContent(string path)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreWhitespace = true;
settings.ConformanceLevel = ConformanceLevel.Auto;
settings.IgnoreComments = true;
using (XmlReader reader = XmlReader.Create("something.xml", settings))
{
reader.MoveToContent();
reader.Read();
XmlDocument doc = new XmlDocument();
doc.LoadXml(reader.ReadOuterXml());
IXmlNode node = doc.SelectSingleNode(path);
return node.InnerText;
}
}
When I pass any form of xpath, node gets the value of null. I'm using the reader to get the first child of root node, and then use XMLDocument to create one from that xml. Since it's Windows 8, apparently, I can't use XPathSelectElements method and this is the only way I can't think of. Is there a way to do it using this, or any other logic?
Thank you in advance for your answers.
[UPDATE]
Let's say XML has this general form:
<nodeone attributes...>
<nodetwo attributes...>
<nodethree attributes... />
<nodethree attributes... />
<nodethree attributes... />
</nodetwo>
</nodeone >
I expect to get as a result nodetwo and all of its children in the form of xml string when i pass "/nodeone/nodetwo" or "//nodetwo"
I've come up with this solution, the whole approach was wrong to start with. The problematic part was the fact that this code
reader.MoveToContent();
reader.Read();
ignores the namespace by itself, because it skips the root tag. This is the new, working code:
public static async Task<string> ReadFileTest(string xpath)
{
StorageFolder folder = await Package.Current.InstalledLocation.GetFolderAsync("NameOfFolderWithXML");
StorageFile xmlFile = await folder.GetFileAsync("filename.xml");
XmlDocument xmldoc = await XmlDocument.LoadFromFileAsync(xmlFile);
var nodes = doc.SelectNodes(xpath);
XmlElement element = (XmlElement)nodes[0];
return element.GetXml();
}

Categories

Resources