XML and SelectNodes - c#

A pretty newbie question as I rarely work with XML. I'm trying out writing stuff for the Subsonic API. The xml looks like this
<?xml version="1.0" encoding="UTF-8"?>
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.6.0">
<indexes lastModified="1313158157783">
<index name="A">
<artist name="Albums" id="5c5c3139322e3136382e322e31305c566f6c756d655f315c4d757369635c416c62756d73"/>
</index>
<index name="S">
<artist name="Singles" id="5c5c3139322e3136382e322e31305c566f6c756d655f315c4d757369635c53696e676c6573"/>
</index>
</indexes>
</subsonic-response>
I'm just trying to get the index nodes.
I'm trying this, but not sure if I am doing this right. Both the SelectNodes and SelectSingleNode are returning emtpy. I'm sure I am missing something simple.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(index.NameTable);
nsmgr.AddNamespace("", "http://subsonic.org/restapi");
XmlNodeList xnList = index.SelectNodes("/subsonic-response/indexes/index", nsmgr);
XmlNode mainnode = index.SelectSingleNode("/subsonic-response", nsmgr);
foreach (XmlNode xn in xnList)
{
}
I've tried with and without the namespacemanager and it's the same thing

Try using a non-empty XML namespace prefix:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(index.NameTable);
nsmgr.AddNamespace("x", "http://subsonic.org/restapi");
XmlNodeList xnList = index.SelectNodes("/x:subsonic-response/x:indexes/x:index", nsmgr);
XmlNode mainnode = index.SelectSingleNode("/x:subsonic-response", nsmgr);
I've had trouble with trying to use the empty string as a (default) XML namespace prefix

How about:
nsmgr.AddNamespace("x", "http://subsonic.org/restapi");
And:
XmlNodeList xnList = index.SelectNodes("/x:subsonic-response/x:indexes/x:index", nsmgr);

Related

Null return on XmlDocument.SelectSingleNode through valid xpath

I currently have the following code
nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("soapenv", soapenv_namespace);
nsmgr.AddNamespace("de", de_namespace);
XmlNode xnEnvelope = xmlDoc.SelectSingleNode("//soapenv:Envelope", nsmgr);
XmlNode xnBody = xmlDoc.SelectSingleNode("//soapenv:Envelope/soapenv:Body", nsmgr);
XmlNode xnMessage = xnBody.SelectSingleNode("//soapenv:Envelope/soapenv:Body/message", nsmgr);
Which parses the following xml (truncated for readibility)
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<message xmlns="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse" xmlns:ns2="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractReferenceResponse" xmlns:ns3="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractRequest" xmlns:ns4="http://www.origostandards.com/schema/tech/v1.0/SOAPFaultDetail">
<de:m_content .....
Problem is the line
XmlNode xnMessage = xnBody.SelectSingleNode("//soapenv:Envelope/soapenv:Body/message", nsmgr); returns null when i'd expect it to return the message element.
I highly suspect its to do with the blank namespace I have configured but I cant find the right combination of values to get it working.
Any pointers would be appreciated.
You have introduced default namespace here :
xmlns="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse"
which causes message element and all of it's descendants without prefix to be recognized as in that default namespace (unless the descendant element has local default namespace). To access element in default namespace, simply register a prefix, for example d, and map it to the default namespace uri :
nsmgr.AddNamespace("d", "http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse");
Then use the newly registered prefix accordingly in the XPath expression :
XmlNode xnBody = xmlDoc.SelectSingleNode("//soapenv:Envelope/soapenv:Body", nsmgr);
XmlNode xnMessage = xnBody.SelectSingleNode("d:message", nsmgr);
This is working
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\Users\DummyUser\Desktop\Noname1.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("de", "http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse");
XmlNode xnEnvelope = xmlDoc.SelectSingleNode("//soapenv:Envelope", nsmgr);
XmlNode xnBody = xnEnvelope.SelectSingleNode("//soapenv:Body", nsmgr);
XmlNode xnMessage = xnBody.SelectSingleNode("de:message", nsmgr);
and xml file is
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<message xmlns="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractDetailResponse" xmlns:ns2="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractReferenceResponse"
xmlns:ns3="http://www.origostandards.com/schema/ce/v2.1/CEBondSingleContractRequest"
xmlns:ns4="http://www.origostandards.com/schema/tech/v1.0/SOAPFaultDetail">
This is my sample message
</message>
</soapenv:Body>
</soapenv:Envelope>

Trying to change a XML node with no success

I'm trying to change a the value for the model atribute from the following .xml file.
<MTConnectDevices xmlns="urn:mtconnect.org:MTConnectDevices:1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mtconnect.org:MTConnectDevices:1.1 http://www.mtconnect.org/schemas/MTConnectDevices_1.1.xsd">
<Header version="1.1" sender="Company MTConnect Instance" creationTime="2010-08-26T19:00:47-07:00" instanceId="2" bufferSize="131072" />
<Devices>
<Device name="XX" iso841Class="1" uuid="000" id="id1001">
<Description manufacturer="name" serialNumber="Serial Number" model="UNDEFINED">
</Description>
This is what I've tried but it's not working as it's not changing the value for model.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(mypath);
var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
var node = xmlDoc.SelectSingleNode("/ns:MTConnectDevices/ns:Header/ns:Devices/ns:Device/ns:Description", nsmgr);
node.Attributes["model"].Value = "changed";
xmlDoc.Save(mypath);
Can anyone give me a hand and tell me how to fix this?
Your xml contains namespaces, so you have to use them while retrieving node.
It can be done something like this:
var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
var node = xmlDoc.SelectSingleNode("/ns:MTConnectDevices/ns:Devices/ns:Device/ns:Description", nsmgr);

Unable to Read XML using C# and XmlDocument

I would like to read a XML File with C#, but i always get an error.
This is my XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<OMDS xmlns="urn:omds20" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:omds20 ./omds26-00.xsd">
<PAKET VUNr="014" PaketZpktErstell="2014-08-29T10:45:08.575" PaketZpktLetztErstell="2014-08-29T10:45:08.575" PaketInhCd="VM" PaketUmfCd="G" VUVersion="26-00" DVRNrAbs="0">
<PERSON ....
<PERSON ....
<PERSON ....
I would like to read this XML, but XMLContentNodes is always null. So i am unable to get the SelectSingleNode with this Path, but i cant find out what should be wrong here?
XmlDocument doc = new XmlDocument();
doc.Load(openFileDialog1.FileName);
XmlNode XMLContentNodes = doc.SelectSingleNode("/OMDS/PAKET"); // Error Here
XmlNodeList PersonNodeList = XMLContentNodes.SelectNodes("PERSON");
foreach (XmlNode node in PersonNodeList)
{
.....
Any help would be greatly appreciated.
The usual namespace problem. Try
XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable());
mgr.AddNamespace("d", "urn:omds20");
XmlNode XMLContentNodes = doc.SelectSingleNode("/d:OMDS/d:PAKET", mgr);
XmlNodeList PersonNodeList = XMLContentNodes.SelectNodes("d:PERSON", mgr);
You'll need to add the namespace urn:omds20 to the doc XmlDocument object after loading your XML file in it. It will look like the following:
XmlDocument doc = new XmlDocument();
doc.Load(openFileDialog1.FileName);
XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(doc.NameTable);
xmlnsManager.AddNamespace("omds20", "urn:omds20");
Then you can query for the PAKET node like this:
XmlNode paketNode = doc.SelectSingleNode("/omds20:OMDS/omds20:PAKET", xmlnsManager);

Cannot Parse a Xmlement with Xpath Correctly

i have web service that returns a xmlement like below
<Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Type>C</Type>
<AppDate>2012-05-01T00:00:00</AppDate>
<Applicants>
<ID>1234</ID>
</Applicants>
<Applicants>
<ID>0</ID>
</Applicants>
<Status>O</Status>
</Application>
on my client side
i have a code like this
XmlElement root = proxy.CallWebservice();
XmlNodeList nodeList;
nodeList = root.SelectNodes("/Application/Applicants");
foreach (XmlNode applicants in nodeList)
{
Console.WriteLine(applicants.InnerXml);
}
PROBLEM: i cannot get anything to output.
BUT
if i do this
File.WriteAllText(#"d:\output.xml", root.OuterXml.ToString());
XmlDocument doc = new XmlDocument();
doc.Load(#"d:\output.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList nodeList;
nodeList = root.SelectNodes("/Application/Applicants");
foreach (XmlNode title in nodeList)
{
Console.WriteLine(title.InnerXml);
}
IT WORKS, i do not want to have to write to the file to just read the nodes. what am i doing wrong?
i had to use
XmlNodeList nodeList;
nodeList = root.SelectNodes("Applicants");
as my root was application

XML - how to use namespace prefixes

I have this XML at http://localhost/file.xml:
<?xml version="1.0" encoding="utf-8"?>
<val:Root xmlns:val="http://www.hw-group.com/XMLSchema/ste/values.xsd">
<Agent>
<Version>2.0.3</Version>
<XmlVer>1.01</XmlVer>
<DeviceName>HWg-STE</DeviceName>
<Model>33</Model>
<vendor_id>0</vendor_id>
<MAC>00:0A:DA:01:DA:DA</MAC>
<IP>192.168.1.1</IP>
<MASK>255.255.255.0</MASK>
<sys_name>HWg-STE</sys_name>
<sys_location/>
<sys_contact>
HWg-STE:For more information try http://www.hw-group.com
</sys_contact>
</Agent>
<SenSet>
<Entry>
<ID>215</ID>
<Name>Home</Name>
<Units>C</Units>
<Value>27.7</Value>
<Min>10.0</Min>
<Max>40.0</Max>
<Hyst>0.0</Hyst>
<EmailSMS>1</EmailSMS>
<State>1</State>
</Entry>
</SenSet>
</val:Root>
I am trying to read this from my c# code:
static void Main(string[] args)
{
var xmlDoc = new XmlDocument();
xmlDoc.Load("http://localhost/file.xml");
XmlElement root = xmlDoc.DocumentElement;
// Create an XmlNamespaceManager to resolve the default namespace.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("val", "http://www.hw-group.com/XMLSchema/ste/values.xsd");
XmlNodeList nodes = root.SelectNodes("/val:SenSet/val:Entry");
foreach (XmlNode node in nodes)
{
string name = node["Name"].InnerText;
string value = node["Value"].InnerText;
Console.Write("name\t{0}\value\t{1}", name, value);
}
Console.ReadKey();
}
}
Problem is that the node is empty. I understand this is a common newbie problem when reading XML, still not able to solve what I am doing wrong, probably something with the Namespace "val" ?
You need to pass the namespace manager into the SelectNodes()
method.
Edit: corrected code
XmlNodeList nodes = root.SelectNodes("/val:Root/SenSet/Entry", nsmgr);
Just change you Xpath to:
XmlNodeList nodes1 = root.SelectNodes("/val:Root/SenSet/Entry",nsmgr);
Or:
XmlNodeList nodes = root.SelectNodes("SenSet/Entry");
Your xpath query string should be:
XmlNodeList nodes = root.SelectNodes("/val:Root/SenSet/Entry", nsmgr);
or more concisely,
XmlNodeList nodes = root.SelectNodes("//SenSet/Entry", nsmgr);

Categories

Resources