I want to read complete XML element, value, attribute path - c#

Can any friends help on this.
Now I want to read a complete path when I get a value.
<?xml version="1.0" encoding="UTF-8" ?>
<Element xsi:schemaLocation="http://localhost/AML/CaseInvestigationMangement/Moduli/XmlImportControls/xsdBorrow.xsd xsd2009027_kor21.xsd" Kod="370" xmlns="http://localhost/AML/CaseInvestigationMangement/Moduli/XmlImportControls/xsdBorrow.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
/2001/XMLSchema-instance">
<ANode>
<BNode>
<CNode>
<Example>
<Name>John</Name>
<NO>001</NO>
</Example>
</CNode>
</BNode>
<ID>1234</ID>
<Date>2011-10-01</Date>
</ANode>
<ANode>
<BNode>
<CNode>
<Example>
<Name>Mike</Name>
<NO>002</NO>
</Example>
</CNode>
</BNode>
<ID>5678</ID>
<Date>2011-03-31</Date>
</ANode>
</Element>
Now I want to read a complete path when I get a value, like NO element then I want to store complete path NO->Example->Cnode->Bnode->Anode. please help...
I have used XMLTextReader to read xml element and value. for more reference please click I want to read the xml sub sub sub node name and value

With xml linq, you can do it as below:
var doc = XDocument.Load(#"fileUri");
var paths=doc.Descendants()
.Where(e=>!(e.HasElements || String.IsNullOrEmpty(e.Value)))
.Select(e=>e.Name+"->"+
String.Join("->",e.Ancestors().Select(a=>a.Name)));

Related

How to add data after xml in c# and read the xml after?

I've got to create a file with xml header and after that i have to put normal data, smthing like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Header>
<Algorithm>alg</Algorithm>
<nod2>aaa</nod2>
<nod3>bbb</nod3>
<node>
<User>
<Email />
<SessionKey />
</User>
</node>
</Header>
Data of the file....
I've already got the code to write it to the file.
Code for that part:
private void setHeader(FileStream output, string nod2, string nod3, string )
{
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", "yes");
doc.AppendChild(docNode);
XmlNode header = doc.CreateElement("Header");
doc.AppendChild(header);
XmlNode algorithm = doc.CreateElement("Algorithm");
algorithm.InnerText = "alg";
header.AppendChild(algorithm);
XmlNode node2= doc.CreateElement("nod2");
node2.InnerText = nod2;
header.AppendChild(node2);
XmlNode node3= doc.CreateElement("nod3");
node3.InnerText = nod3;
header.AppendChild(node3);
XmlNode node= doc.CreateElement("node");
header.AppendChild(node);
XmlNode user1 = doc.CreateElement("User");
node.AppendChild(user1);
XmlNode mail = doc.CreateElement("Email");
user1.AppendChild(mail);
XmlNode sessionKey = doc.CreateElement("SessionKey");
user1.AppendChild(sessionKey);
doc.Save(output);
}
It work's pretty well, but when i want to read it with
private void readHeader(FileStream input, out string algorithm)
{
XmlDocument doc = new XmlDocument();
doc.Load(input);
}
I got an error that when the "Data of the file..." starts: "Data on the root level is invalid".
Is there a way to do it with the data after whole xml, or have i to add the data as a node?
This can be done in multiple ways. In comments, you've indicated that the best way is unacceptable for reasons outside the scope of the discussion. For completeness, I'm going to put that one first anyway. Skip down to tl;dr for what I think you'll have to end up doing.
The preferred way to do this is to base64 encode the encrypted data and put it in a CDATA block:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<File>
<Header>
<Algorithm>alg</Algorithm>
<nod2>aaa</nod2>
<nod3>bbb</nod3>
<node>
<User>
<Email />
<SessionKey />
</User>
</node>
</Header>
<Data><![CDATA[
ICAgIFhtbE5vZGUgYWxnb3JpdGhtID0gZG9jLkNyZWF0ZUVsZW1lbnQoIkFsZ29yaXRobSIpOw0K
ICAgIGFsZ29yaXRobS5Jbm5lclRleHQgPSAiYWxnIjsNCiAgICBoZWFkZXIuQXBwZW5kQ2hpbGQo
YWxnb3JpdGhtKTsNCiAgICBYbWxOb2RlIG5vZGUyPSBkb2MuQ3JlYXRlRWxlbWVudCgibm9kMiIp
Ow0KICAgIG5vZGUyLklubmVyVGV4dCA9IG5vZDI7DQogICAgaGVhZGVyLkFwcGVuZENoaWxkKG5v
ZGUyKTsNCiAgICBYbWxOb2RlIG5vZGUzPSBkb2MuQ3JlYXRlRWxlbWVudCgibm9kMyIpOw0KICAg
IG5vZGUzLklubmVyVGV4dCA9IG5vZDM7DQogICAgaGVhZGVyLkFwcGVuZENoaWxkKG5vZGUzKTs=
]]></Data>
</File>
That's the canonical answer to this question.
But you've told me that in your case, a requirement has been imposed that you can't do it that way.
Second choice is MIME (actually, MIME might be the first choice and the above might be the second). But I have a feeling they won't like MIME either.
Third choice, read the file as a string and search for some marker that's inserted between the XML and the binary data, something like a MIME boundary.
tl;dr
If they won't let you add such a marker to the file (and I bet they won't), search for the first occurrence of the substring "</Header>":
var xml = File.ReadAllText(filePath);
var endTag = "</Header>";
var headerXML = xml.Substring(0, xml.IndexOf(endTag) + endTag.Length);
var xdHeader = new XmlDocument();
xdHeader.LoadXml(headerXML);
I tested your code with writing directly to a file, doc.Save(#"c:\temp\test1.xml");
And loading from that file works fine. So there is nothing wrong with your xml document. Check your FileStream. Do you flush and close it properly? Does it have UTF-8 encoding?
What's the input in the node strings. Nothing that is invalid according to xml rules?
After a single root node, only comments and processor instructions can be written to xml. So, you can try to write your data in the comments.
It will look like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Header>
...
</Header>
<!-- your data -->
<!-- another data -->
This method has limitations: your data may not contain -- (double-hyphen) and may not end in -.
But it is better, of course, not to do so.

How to change xml element value in c#?

<?xml version="1.0" encoding="utf-8"?>
<Settings>
<Code>D:picture\simple</Code>
<Password>picture</Password>
</Settings>
I want to change the value which is inside Code and Password.How can I change the value.
XElement root = XElement.Load("path/to/xml/somewhere");
root.Element("Code").Value= "newcode";
root.Element("Password").Value ="Penis *gnhihihi*";
//only in Linqpad
root.Dump();
And there you have it. This is one way to change it.
It is up to you how you save it back to an xml file

DataContractSerializer and "URL" xml node

I am trying to deserialize a XML file by using DataContractSerializer which containes node called "URL". Like this one:
<?xml version="1.0" encoding="utf-8"?>
<products>
<product ID="8717973147527">
<name>Something</name>
<price currency="EUR">9.00</price>
<URL>http://google.com</URL>
<images>
<image>http://google.com</image>
</images>
</product>
</products>
After deserialization property mapped to URL stays null. If I rename the xml node to "url" (lower case) or any other word it is working fine. The problem is that I am not able to change the XML, so I must find a way to deserialize it. Can anyone help me?
You can use the XmlAttribute to set the name as you expect it on the XML file as:
[Serializable]
public class ClassName
{
// Here set the Xml Name Attribute
[XmlAttribute("URL")]
string Url;
...

How to replace tag names in XML file using C#?

I'm new to XML, so this might be an easy question.
I have a XML file structured as below.
<root>
<Test>
<EmpID>23</EmpID>
<EmpName>Packman</EmpName>
<EmpAge>33</EmpAge>
</Test>
<Test>
<EmpID>34</EmpID>
<EmpName>James</EmpName>
<EmpAge>13</EmpAge>
</Test>
<Test>
<EmpID>53</EmpID>
<EmpName>Nedved</EmpName>
<EmpAge>52</EmpAge>
</Test>
<root>
I want to replace some of elements in the XML file like below
<root>
<Test>
<EmpID name="ID">23</EmpID>
<EmpName name="Nickname">Packman</EmpName>
<EmpAge name = "Age">33</EmpAge>
</Test>
<Test>
<EmpID name="ID">34</EmpID>
<EmpName name="Nickname">James</EmpName>
<EmpAge name = "Age">13</EmpAge>
</Test>
<Test>
<EmpID name="ID">53</EmpID>
<EmpName name="Nickname">Nedved</EmpName>
<EmpAge name = "Age">52</EmpAge>
</Test>
</root>
So basically I want to relace or add? element to attribute.
ex)
<EmpID>value</EmpID> to <EmpID name="ID">value</EmpID>
I've tried some of references, but they didn't work for me.
Below is the one that I tried, but it replaces whole line.
XDocument xdoc1 = XDocument.Load("C:\\Test\\Test.xml");
XElement one = xdoc1.Descendants("EmpID").First();
one.ReplaceWith("EmpID name=NickName");
xdoc1.Save("C:\\Test\\Test_Modified.xml");
The point is center 'value' should not change. See below.
<EmpID>value</EmpID> to <EmpID name="ID">value</EmpID>
Please give me some ideas how to solve this.
All you have to do is set the attribute:
one.SetAttributeValue("name", "ID");
To change the attribute you can go with above solution:
one.SetAttributeValue("name", "ID");
And the easiest way I found to rename a node is:
xmlNode.InnerXmL = newNode.InnerXml.Replace("OldName>", "NewName>")
Don't include the opening < to ensure that the closing tag is renamed as well.
You can refer this link also:
http://www.goodgord.com/2006/10/how-to-rename-xml-node-in-c.html

Why XDocument can't get element out of this wellform XML text?

I'm trying to get the value of the Address element from the following XML text, but it's not finding it unless I remove xmlns="http://www.foo.com" from the Root element. However, the XML is valid even with it. What's the problem here?
Since I'm getting the XML text from a web service, I don't have control over it, but I can strip out the xmlns part if I have to as the last resort.
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.foo.com">
<Address>Main St SW</Address>
</Root>
var doc = XDocument.Parse(xmlTextAbove);
var address = doc.Descendants().Where(o => o.Name == "Address").FirstOrDefault();
Console.WriteLine(address.Value); // <-- error, address is null.
As your xml contains a namespace, you have to mention that in code. This will work:
XNamespace nsSys = "http://www.foo.com";
XElement xDoc = XElement.Load("1.xml");
XElement xEl2 = xDoc.Descendants(nsSys + "Address").FirstOrDefault();
However I had to change your xml a little bit, as it contained repeated xmlns:xsi and xmlns:xsd which should occur only once per xml format:
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.foo.com" >
<Address>Main St SW</Address>
</Root>
Related article in MSDN: XNamespace Class
The document root's XML namespace is included in the textual representation of o.Name, which is actually an instance of XName so the condition never matches.
The easiest fix is to use LocalName for the comparison:
.Where(o => o.Name.LocalName == "Address")

Categories

Resources