XmlNodeList remains empty - why is that so? - c#

Okay, this had me occupied for several hours now and still I have no explanation for it:
My XML starts like this:
<?xml version="1.0" encoding="iso-8859-1"?>
<ISO15745Profile xmlns="http://www.profibus.com/GSDML/2003/11/DeviceProfile" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.profibus.com/GSDML/2003/11/DeviceProfile ..\XSD\GSDML-DeviceProfile-v2.1.xsd">
<ProfileHeader>
<ProfileIdentification>PROFINET Device Profile</ProfileIdentification>
<ProfileRevision>1.00</ProfileRevision>
<ProfileName>Device Profile for PROFINET Devices</ProfileName>
<ProfileSource>PROFIBUS Nutzerorganisation e. V. (PNO)</ProfileSource>
<ProfileClassID>Device</ProfileClassID>
<ISO15745Reference>
<ISO15745Part>4</ISO15745Part>
<ISO15745Edition>1</ISO15745Edition>
<ProfileTechnology>GSDML</ProfileTechnology>
</ISO15745Reference>
</ProfileHeader>
<ProfileBody>
<DeviceIdentity DeviceID="0x000A" VendorID="0x00B0">
<InfoText TextId="InfoTextId1"/>
<VendorName Value="Phoenix Contact GmbH"/>
</DeviceIdentity>
<DeviceFunction>
<Family MainFamily="I/O" ProductFamily="Inline"/>
</DeviceFunction>
<ApplicationProcess>
<DeviceAccessPointList>
<DeviceAccessPointItem ID="DIM 1" FixedInSlots="0" PhysicalSlots="0..64" MinDeviceInterval="32" ModuleIdentNumber="0x00000300" DNS_CompatibleName="IL-PN-BK-2TX" ImplementationType="ERTEC200" ObjectUUID_LocalIndex="1">
<ModuleInfo>
<Name TextId="IL PN BK DI8 DO4 2TX"/>
<InfoText TextId="InfoTextId1"/>
<VendorName Value="Phoenix Contact"/>
<OrderNumber Value="2703994"/>
</ModuleInfo>
<SubslotList>
<SubslotItem SubslotNumber="32768" TextId="SubSlot_Interface"/>
<SubslotItem SubslotNumber="32769" TextId="SubSlot_Port1"/>
<SubslotItem SubslotNumber="32770" TextId="SubSlot_Port2"/>
</SubslotList>
<IOConfigData MaxInputLength="512" MaxOutputLength="512"/>
<UseableModules>
<ModuleItemRef FixedInSlots="1" ModuleItemTarget="1"/>
<ModuleItemRef AllowedInSlots="4..64" ModuleItemTarget="2"/>
<ModuleItemRef AllowedInSlots="4..64" ModuleItemTarget="3"/>
<ModuleItemRef AllowedInSlots="4..64" ModuleItemTarget="4"/>
<ModuleItemRef AllowedInSlots="4..64" ModuleItemTarget="5"/>
<ModuleItemRef AllowedInSlots="4..64" ModuleItemTarget="6"/>
...
Now what I'm trying to do is work with the AllowedInSlots, but when creating a XmlNodeList with
XmlDocument gsdml = new XmlDocument();
gsdml.Load(fpfad);
XmlNodeList ModuleItemRef = gsdml.SelectNodes("/ISO15745Profile/ProfileBody/ApplicationProcess/DeviceAccessPointList/DeviceAccessPointItem/UseableModules");
that XmlNodeList remains empty. What am I doing wrong? I thought that maybe I had to work with the Namespacemanager and tried that, but that didn't do anything.
This is what I tried earlier:
XmlDocument gsdml = new XmlDocument();
gsdml.Load(fpfad);
XmlNamespaceManager mgr = new XmlNamespaceManager(gsdml.NameTable);
mgr.AddNamespace("iso", "http://www.profibus.com/GSDML/2003/11/DeviceProfile");
XmlNodeList ModuleItemRef = gsdml.SelectNodes("/iso:ISO15745Profile/ProfileBody/ApplicationProcess/DeviceAccessPointList/DeviceAccessPointItem/UseableModules", mgr);
It didn't work, though, so something there has to be wrong.
2nd Edit:
Including the prefix with every part of the path did the trick.

It is indeed the namespace manager.
xmlns="http://www.profibus.com/GSDML/2003/11/DeviceProfile"
means that everything is in that namespace (unless another default is declared, or an element declares its own namespace). You will need to use a namespace manager to search in that namespace.

Related

I'm getting an xpath error when navigating to an element in the soap message

Programming Langauge - c#.
Below mentioned error is showing.
Unhandled Exception: System.Xml.XPath.XPathException: Namespace Manager or XsltC
ontext needed. This query has a prefix, variable, or user-defined function.
This is the code that I wrote to return the inner text.
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(#"C:\test\myfile.xml");
var nsmgr = new XmlNamespaceManager(xmldoc.NameTable);
nsmgr.AddNamespace("env", "http://schemas.xmlsoap.org/soap/envelope/");
nsmgr.AddNamespace("ns1", "http://sse/ECOM:1.0:schema:messages");
nsmgr.AddNamespace("wsa", "http://www.w3.org/2005/08/addressing");
XmlNode node = xmldoc.SelectsingleNode("/*/env:Body/env:response/env:customerAccountsGrp[1]/env:customerAccountID");
Console.WriteLine(xmldoc.SelectSingleNode("/*/env:Body/env:response/env:customerAccountsGrp[1]/env:customerAccountID").InnerText);
This is the soap message
<env:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://www.w3.org/2005/08/addressing">
<env:Header>
<wsa:MessageID>urn:5C4DCC70E6F411E69F7EF5AAD683B4B3</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:ReplyTo><wsa:FaultTo> <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:FaultTo>
</env:Header>
<env:Body>
<response
xmlns:ns0="urn:sse:ECOM:1.0:schema:messages"
xmlns="urn:sse:ECOM:1.0:schema:messages">
<ns0:customerAccountsGrp>
<ns0:customerAccountID>1212121212</ns0:customerAccountID>
<ns0:customerAccountStatus>AC</ns0:customerAccountStatus>
<ns0:serviceType>AB</ns0:serviceType>
<ns0:brandCode>XXX </ns0:brandCode>
<ns0:affinityType> </ns0:affinityType>
<ns0:paymentType>VV</ns0:paymentType>
</ns0:customerAccountsGrp><ns0:customerAccountsGrp>
<ns0:customerAccountID>4545454545445</ns0:customerAccountID>
<ns0:customerAccountStatus>BC</ns0:customerAccountStatus>
<ns0:serviceType>FH</ns0:serviceType>
<ns0:brandCode>SE</ns0:brandCode>
<ns0:affinityType></ns0:affinityType>
<ns0:paymentType>NM</ns0:paymentType>
</ns0:customerAccountsGrp>
Can anyone help me on this issue?
Best Regards.

Reading an XML document with XMLDocument C# 'password' string not returning

I'm trying to read the text in between <keyMaterial></keyMaterial>
I tried using //WLANProfile/MSM/security/sharedKey as the element route, seen in the code below. It refuses to return a value. I have run through the debugger and after the breakpoint at the line: XmlNodeList sharedKeyNodes = wifiProfile.SelectNodes("//WLANProfile/MSM/security/sharedKey");
the SharedKeyNodes object doesn't return a count for. I know it's just a matter of figuring out the element route so I'm not coming here completely hopeless...
System.Xml.XPathNodeList
My XML looks like this:
<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
<name>nosignal</name>
<SSIDConfig>
<SSID>
<hex>6E6F7369676E616C</hex>
<name>nosignal</name>
</SSID>
<nonBroadcast>true</nonBroadcast>
</SSIDConfig>
<connectionType>ESS</connectionType>
<connectionMode>auto</connectionMode>
<autoSwitch>false</autoSwitch>
<MSM>
<security>
<authEncryption>
<authentication>WPA2PSK</authentication>
<encryption>AES</encryption>
<useOneX>false</useOneX>
<FIPSMode xmlns="http://www.microsoft.com/networking/WLAN/profile/v2">false</FIPSMode>
</authEncryption>
<sharedKey>
<keyType>passPhrase</keyType>
<protected>true</protected>
<keyMaterial>01000000D</keyMaterial>
</sharedKey>
</security>
</MSM>
</WLANProfile>
[ EDIT with the help of LB the new code looks like this and it WORKS! ]
[ For anyone that is struggling with a similar problem. ]
My Class is:
class ProfileManager
{
public static string readProfile() {
XmlDocument wifiProfile = new XmlDocument();
string path = #"C:\temp\nosignal.xml";
string password = "";
wifiProfile.Load(path);
XmlNamespaceManager mgr = new XmlNamespaceManager(wifiProfile.NameTable);
mgr.AddNamespace("ns", "http://www.microsoft.com/networking/WLAN/profile/v1");
XmlNodeList sharedKeyNodes = wifiProfile.SelectNodes("//ns:WLANProfile/ns:MSM/ns:security/ns:sharedKey", mgr);
foreach (XmlNode itemNode in sharedKeyNodes)
{
XmlNode keyMaterialNode = itemNode.SelectSingleNode("ns:keyMaterial", mgr);
if (keyMaterialNode != null)
{
password = keyMaterialNode.InnerText;
}
}
return password;
}
}
I'm close, but still just a bit stuck. Any help would be appreciated!!! Thank you!
You don't use the default XmlNamespace "http://www.microsoft.com/networking/WLAN/profile/v1"
wifiProfile.Load(path);
XmlNamespaceManager mgr = new XmlNamespaceManager(wifiProfile.NameTable);
mgr.AddNamespace("ns", "http://www.microsoft.com/networking/WLAN/profile/v1");
XmlNodeList sharedKeyNodes = wifiProfile.SelectNodes("//ns:WLANProfile/ns:MSM/ns:security/ns:sharedKey",mgr);

How to process webdav server XML request in C#

I am writing a custom WebDAV server in C#. One of the client test programs I am using is NetDrive and it claims and appears to be a WebDAV compliant client. My problem is I am receiving a request on the server in the following format:
<?xml version="1.0" encoding="utf-8"?>
<propfind xmlns="DAV:">
<allprop/>
</propfind>
But other clients do this:
<?xml version="1.0" encoding="utf-8"?>
<D:propfind xmlns:D="DAV:">
<D:allprop/>
</D:propfind>
The two different namespace formats keep on fooing up my logic to look for the "allprop" element. My code looks a bit like this:
string xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><propfind xmlns=\"DAV:\"><allprop/></propfind>"; //Hardcode to make all the StackOverflow users' lives easier
XPathDocument doc = new XPathDocument(new StringReader(xml));
XPathNavigator nav = doc.CreateNavigator();
XPathNodeIterator it = nav.Select("/propfind/*");
Now, I know I need to put in some type of namespace manager for the "DAV:", so I tried this:
XmlNamespaceManager nsman = new XmlNamespaceManager(nav.NameTable);
nsman.AddNamespace("", "DAV");
XPathNodeIterator it = nav.Select("/propfind/*", nsman);
But I'm getting no nodes in my iterator for the first XML file. It seems the default namespace isn't working like I thought it should.
What am I doing wrong? How do I query this XML for the existence of an allprop node when the namespace may be the default, or may be explicitly named?
You are using the wrong namespace in your code. Unforunalely the WebDAV specs use
'DAV:' as the namespace for WebDAV nodes and attributes (this seems to be caused by
a missunderstanding of the XML namespace mechanism).
I ended up looking for the namespace URI (DAV:) and adding it if it didn't exist. Then I just did a namespace-qualified SELECT and it worked in all my test cases:
XPathDocument document = new XPathDocument(xml);
XPathNavigator navigator = document.CreateNavigator();
//Get namespaces & add them to the search
bool hasDAV = false;
string davPrefix = "D";
XmlNamespaceManager nsman = new XmlNamespaceManager(navigator.NameTable);
foreach (KeyValuePair<string, string> nskvp in navigator.GetNamespacesInScope(XmlNamespaceScope.All))
{
if (string.Compare(nskvp.Value, "DAV:", StringComparison.InvariantCultureIgnoreCase) == 0)
{
hasDAV = true;
davPrefix = nskvp.Key;
}
nsman.AddNamespace(nskvp.Key, nskvp.Value);
}
if (!hasDAV)
nsman.AddNamespace(davPrefix , "DAV:");
XPathNodeIterator iterator = navigator.Select("/" + davPrefix + ":" + WebDavXML.PropFind + "/*", nsman);

how to parse a XML in C# using NamspaceManager,XML is having namespaces defined at elements level

i wish to parse following XML
<?xml version="1.0" encoding="UTF-8"?>
<product xmlns="http://products.org">
<make xmlns="http://camera.org">
<model>Camry</model>
</make>
<make xmlns="http://tv.org">
<model>Sony</model>
</make>
</product>
Code written to parse it
This is how i m writing Parsing Code
but in last i m getting null inxmlNode object. Can u tell what more to do .
You can't ignore namespaces in XPath.* The elements in your document all have non-blank namespace URI's.
Your question title indicates you're on the right track: you need to explicitly bind the URI's to prefixes using an XmlNamespaceManager, and use those prefixes in your path expressions.
This program is tested against your input document
using System;
using System.Xml;
public class XPathNamespace
{
public static void Main() {
XmlDocument doc = new XmlDocument();
doc.Load("test1.xml");
XmlNamespaceManager xnm = new XmlNamespaceManager(doc.NameTable);
xnm.AddNamespace("p", "http://products.org");
xnm.AddNamespace("c", "http://camera.org");
xnm.AddNamespace("t", "http://tv.org");
ShowNode(doc.SelectSingleNode("/p:product", xnm));
ShowNode(doc.SelectSingleNode("/p:product/c:make", xnm));
ShowNode(doc.SelectSingleNode("/p:product/t:make", xnm));
}
private static void ShowNode(XmlNode node) {
Console.WriteLine("<{0}> {1}",
node.LocalName,
node.NamespaceURI);
}
}
and it produces the following output
<product> http://products.org
<make> http://camera.org
<make> http://tv.org
Hope this helps.
(*) This doesn't mean you can't ignore the exact namespace in your XPath. For example, you could match
/*[local-name()='product']
But that's a workaround and illustrates that you still have to deal with the presence of a namespace somehow or other.
This is the best example for you. Please have a look.
http://www.codeproject.com/KB/cpp/myXPath.aspx

XmlDocument and getting specific Attributes using xPath

I have seen a couple of examples on here where Xpath is used in conjunction with XmlDocument to get a specific attribute from an XmlDocument Node.... Example
Console.WriteLine(xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element/#name").Value.ToString());
For some reason I am getting a "Object reference not set to an instance of an object." exception. Whenever I run across that particular line of code. I have a little test app that I have set up to test out different things before I put them into my main project...
Here is the code for that...
namespace ReadXml
{
class Program
{
static void Main(string[] args)
{
//string fulXmlPath = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/templateExample.xml");
XDocument xDocument = XDocument.Load("C:\\Users\\derekww\\Documents\\XML Documents\\templateExample.xml");
XElement elem = xDocument.Element("dataTemplateSpecification"); ;
XmlDocument xmlDocument = new XmlDocument();
StreamReader file = new StreamReader("C:\\Users\\derekww\\Documents\\XML Documents\\templateExample.xml");
xmlDocument.Load(file);
//XmlDocument theDoc = new XmlDocument();
//using (var xmlReader = xDocument.CreateReader())
//{
// xmlDocument.Load(xmlReader);
//}
//Console.WriteLine(elem.ToString());
XmlNode xNode = xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element");
Console.WriteLine("WORK PLEASE!!!! {0}", xNode.Value.ToString());
//Console.WriteLine(xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element/#name").Value.ToString());
//Console.WriteLine("This better Work>>>> {0}", xmlDocument.Attributes["/dataTemplateSpecification/templates/template/elements/element/#name"].Value);
Console.ReadLine();
//Console.WriteLine("This better Work>>>> {0}", xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element/#name").Value);
//foreach (String AttVal in xmlDocument.SelectSingleNode("//dataTemplateSpecification/templates/template/elements/element/#name").Value)
{
//Console.WriteLine("This better Work>>>> {0}", AttVal);
}
}
}
}
Here is part of the XML that I used...
<?xml version="1.0" encoding="utf-8"?>
<dataTemplateSpecification id="id1" name="name1" xmlns="http://EADIS.upmc.com /DataTemplateSpecification.xsd">
<description xmlns="">
<html>text</html>
</description>
<templates xmlns="">
<template>
<elements>
<element id="element0" name="PatientId" display="Patient ID" dataType="String" value="0101010111111" visable="false" readOnly="true">
<validation>
<rules>
<rule id="0" test="#element0.value == ''">
<fail>
<html><b>Patient ID is null, value must be present</b></html>
</fail>
</rule>
</rules>
</validation>
</element>
</elements>
</template>
<templates>
I just showed you the part that you need to understand the xml structure. I assure you that it is well formed. I think I asked this question before but somehow or the other it didn't get posted (maybe I forgot, who knows). Any help with this would be greatly appreciated. If I come up with a reason for why it isn't working I will be sure to let you guys know.
Thank You.
Why can't you use this XPath:
xmlDocument.SelectSingleNode("//templates/template/elements/element/#name").Value
You need to specify the namespace of the XML file in your code.
See here for more info: How to select xml root node when root node has attribute?

Categories

Resources