C#: Read XML Attribute - c#

Using C#2.0 and VIsualStudio2005
I'm trying to access the "DisplayName" inside "MonitorResponseRecord"
from an XML file like the one Below:
<Magellan xsi:schemaLocation="http://tempuri.org/XMLSchema.xsd ..\Schema\Configuration.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<SchemaVersion>1.0</SchemaVersion>
<MonitorScope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="CleanStationChemicalManifoldFeed5" xmlns="http://tempuri.org/XMLSchema.xsd">
<PersonalSafety>
<MonitorResponseRecord Enabled="true" DisplayName="ChemicalManifoldFeed5ControllerFault">
<ExpressionMonitor>
<Expression>(ChemicalManifold.Feed5.DispenseValve = Open) and ((ChemicalManifold.Feed5.ViolatedRegion = HighProcess) or (ChemicalManifold.Feed5.ViolatedRegion = LowProcess) or (ChemicalManifold.Feed5.ViolatedRegion = Minimum))</Expression>
<TestInterval>0.1</TestInterval>
<MinimumTimeBetweenResponses>5</MinimumTimeBetweenResponses>
</ExpressionMonitor>
<Response>
<PostAlarm>
<AlarmName>ChemicalManifold_Feed5_ControllerFault</AlarmName>
<Parameter1 />
<Parameter2>Alarm Region = {ChemicalManifold.Feed5.ViolatedRegion}</Parameter2>
<Parameter3>{RecipeName}-{StepName}</Parameter3>
<Parameter4>FlowSetpoint = {ChemicalManifold.Feed5.Setpoint}-LPM, ActualFlow = {ChemicalManifold.Feed5.FlowMeter}-LPM</Parameter4>
</PostAlarm>
<ResponseEvent>
<TargetResource />
<Event>PA</Event>
<Reason>ChemicalSupply</Reason>
</ResponseEvent>
</Response>
</MonitorResponseRecord>
</PersonalSafety>
<PersonalSafety>
<MonitorResponseRecord Enabled="true" DisplayName = "PressureValveFailure">
...
...
...and soon
My current C# attempt is as follows, BUT it always hangs up when I try to XmlDocument.Load("");
XmlDocument doc = new XmlDocument();
doc.Load("../UMC0009.Configuration.Root.xml");
string attrVal = doc.SelectSingleNode("MonitorResponseRecord/#DisplayName").Value;
BUUUUT won't work :/ any help out there?
UPDATE:
the exception I recieve is as follows, and occures at the doc.Load("...") line:
{"Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function."} System.Exception {System.Xml.XPath.XPathException}

Your XPath query will be relative to the document root:
doc.SelectSingleNode("MonitorResponseRecord/#DisplayName")
To make it search anywhere in the doc prefix it with double slash:
doc.SelectSingleNode("//MonitorResponseRecord/#DisplayName")
If that still doesn't work I would try the above example after stripping out all those namespace declarations on the two root nodes.
Otherwise, with the namespace declarations you may find you need to define XML namespace mappings and use prefixes in your XPath like:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("x", "http://tempuri.org/XMLSchema.xsd");
doc.SelectSingleNode("//x:MonitorResponseRecord/#DisplayName")

What about:
XmlDocument doc = new XmlDocument();
doc.Load("UMC0009.Configuration.Root.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ns", "http://tempuri.org/XMLSchema.xsd");
string attrVal = doc.SelectSingleNode("//ns:MonitorResponseRecord/#DisplayName", nsmgr).Value;
Using a namespace manager, specify your namespace URI and use it in your XPath.
It works for me.

Related

Getting XML node using XPath returns null

I am trying to get a node in a simple XML, but no matter what I try I always get null.
I am guessing that the issue is the namespace.
I am simply trying to get the value of the ID element, 331377697.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("E:\\0323.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace("cac", "http://xxxxxx Some URL XXXX");
manager.AddNamespace("cbc", "http://xxxxxx Some URL XXXX");
string query = "/StandardBusinessDocument/Invoice/cbc:ID";
XmlNode xmlNode = xmlDoc.SelectSingleNode(query, manager);
The XML:
<StandardBusinessDocument xmlns="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader">
<StandardBusinessDocumentHeader>
...
</StandardBusinessDocumentHeader>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ccts="urn:un:unece:uncefact:documentation:2"
...
</Invoice>
<cbc:UBLVersionID>2.1</cbc:UBLVersionID>
<cbc:CustomizationID>1234</cbc:CustomizationID>
<cbc:ProfileID>1234564</cbc:ProfileID>
<cbc:ID>331377697</cbc:ID>
<cbc:IssueDate>2017-03-23</cbc:IssueDate>
<cbc:InvoiceTypeCode listID="UNCL1001">380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode listID="ISO4217">NOK</cbc:DocumentCurrencyCode>
<cac:OrderReference>
<cbc:ID>146136</cbc:ID>
</cac:OrderReference>
...
You must specify the exact namespaces.
Also you have to specify namespace prefixes for all elements in the XPath.
manager.AddNamespace("nsDoc", "http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader");
manager.AddNamespace("nsInvoice", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2");
manager.AddNamespace("cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2");
string query = "/nsDoc:StandardBusinessDocument/nsInvoice:Invoice/cbc:ID";
It's supposed to work.

Unable to use XmlDocument.SelectSingleNode on XML with Two Namespaces

I'm trying to parse the following XML:
<?xml version="1.0" encoding="utf-8"?>
<A2AAnf:MPPPPPP xsi:schemaLocation="urn:A2AAnf:xsd:$MPPPPPP.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:A2AAnf="urn:A2AAnf:xsd:$MPPPPPP">
<A2AAnf:Num>0</A2AAnf:Num>
<A2AAnf:FIT xmlns="urn:iso:std:iso:20022:xsd:003.001">
<Hdr>
<Inf>
<Mtd>TEST</Mtd>
</Inf>
</Hdr>
</A2AAnf:FIT>
I want to access the <Mtd> tag.
XMLQuire shows the path to be /A2AAnf:MPPPPPP/A2AAnf:FIT/dft:Hdr/dft:Inf/dft:Mtd, but when I'm trying to parse it using the following code:
XmlDocument xmldocument = new XmlDocument();
var xmlNameSpaceManager = new XmlNamespaceManager(xmldocument.NameTable);
xmlNameSpaceManager.AddNamespace("A2AAnf", "urn:A2AAnf:xsd:$MPPPPPP");
try
{
xmldocument.LoadXml(m_XML);
var node = xmldocument.SelectSingleNode("/A2AAnf:MPPPPPP/A2AAnf:FIT/dft:Hdr/dft:Inf/dft:Mtd", xmlNameSpaceManager);
}
I receive the following error:
namespace prefix 'dft' is not defined
And since I can't find "dft" in my XML, I also tried to remove the "dft" prefix and search for the same string without "dft". This time, nothing was returned.
What am I missing?
You have to add dft to your XmlNamespaceManager:
var xmlNameSpaceManager = new XmlNamespaceManager(xmldocument.NameTable);
xmlNameSpaceManager.AddNamespace("A2AAnf", "urn:A2AAnf:xsd:$MPPPPPP");
xmlNameSpaceManager.AddNamespace("dft", "urn:iso:std:iso:20022:xsd:003.001");
The prefixes you use in your XPath query have nothing to do with the prefixes used in the XML document. They are instead the prefixes you define in your XmlNamespaceManager.

Selecting values from an xml document object with XPATH in code behind (c#)

I am trying to select specific values from a xml document using XPath. The xml is stored into a string varibale "tmp". This xml is the result of a query performed on a external API.
sample XML contents:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Results>
<Checks>
<Check id="wbc">
<Linespeed>6000 </Linespeed>
<Provider>BT WBC </Provider>
</Check>
<Check id="adsl">
<Linespeed>2048 </Linespeed>
<Provider>BT ADSL </Provider>
</Check>
</Checks>
</Results>
Using XPATH in code behind I want to be able to select the and only for id=adsl, then store the value in a string variable for later use. I want to achieve this withouth the use of a separate xslt stylesheet.
Here is the code I have written for this but I am getting an error:
//Creating an XPATH epression
String strExpression1;
strExpression1 = "Results/Checks/Check[#id = 'adsl']/Linespeed";
//Loading the xml document
XmlDocument doc;
doc = new XmlDocument();
doc.LoadXml(tmp);
//Create an XmlNamespaceManager to resolve the default namespace.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("bk", "urn:schemas-microsoft-com:xslt");
//Selecting Linespeed from Check id='adsl'
XmlNode Check;
XmlElement root = doc.DocumentElement;
Check = root.SelectSingleNode(strExpression1, nsmgr);
//Assigning the the results of the XPATH expression to the variable Linespeedval
string Linespeedval = Check.ToString();
//Adding a control to display the xpath results of the "tmp" xml objectt
AvailabilityCheckerResults2.Controls.Add(new LiteralControl(Linespeedval));
Any assistance will be greately appreciated! Thanks in advance!
strExpression1 = "/Results/Checks/Check[#id = 'adsl']/Linespeed";
//or strExpression1 = "//Checks/Check[#id = 'adsl']/Linespeed";
//doc has no namespace
Check = root.SelectSingleNode(strExpression1);
....
string Linespeedval = Check.InnerText;
Take a look at this article. It has step by step instruction to parse xml using xpath.
How to query XML with an XPath expression by using Visual C#

Can't parse XML because of the attribute stuck on element

The problem is the ServiceDocument as the xmlns attribute on it.
---Preassigned XML
System.Xml.XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>
<ServiceDocument
xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices\"
>
<BaseUri>
http://xxxx.xxxxx.net/xxx.1/
</BaseUri>
<ProfilesLink>
http://adf.apis.dds.net/af.1/
</ProfilesLink>
<SignedInUser>
<Cid>
4433sfsdfgd
</Cid>
<Uri>
http://fd.apis.afdafd.net/V4.1/cid-xxxxx/adad
</Uri>
</SignedInUser>
<StatusMessageLink>
http://psm.adfa.afd.net/dfa.1/
</StatusMessageLink>
</ServiceDocument>"
);
// Response.Write(xmlDoc.InnerXml);
--//PARSE XML problem is below**
Response.Write(xmlDoc.SelectSingleNode("/ServiceDocument/BaseUri").InnerXml);
You need to assign short aliases to the namespaces using the XMLNamespaceManager.
See this page for an example.
So, to solve your problem:
var xmlNamespaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
xmlNamespaceManager.AddNamespace("ds", "http://schemas.microsoft.com/ado/2007/08/dataservices");
var result = xmlDoc.SelectNodes("/ds:ServiceDocument/ds:BaseUri", xmlNamespaceManager);

SelectSingleNode return null - even with namespace

I know this question has been asked in a similar fashion before, but I can't seem to get this working.
I have some xml:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<Research xmlns="http://www.rixml.org/2005/3/RIXML" xmlns:xalan="http://xml.apache.org/xalan" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" createDateTime="2011-03-29T15:41:48Z" language="eng" researchID="MusiJvs3008">
<Product productID="MusiJvs3008">
<StatusInfo currentStatusIndicator="Yes" statusDateTime="2011-03-29T15:41:48Z" statusType="Published" />
<Source>
<Organization type="SellSideFirm" primaryIndicator="Yes">
<OrganizationID idType="Reuters">9999</OrganizationID>
And I'm trying to read values using xpath:
XPathDocument xmldoc = new XPathDocument(xmlFile);
XPathNavigator nav = xmldoc.CreateNavigator();
XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable);
nsMgr.AddNamespace(string.Empty, "http://www.rixml.org/2005/3/RIXML");
XPathNavigator result = nav.SelectSingleNode("/Research", nsMgr); // <-- Returns null!
But even a simple select of the root node returns null! I am sure I have something wrong with my namespace. Can someone please help?
Ideally I want simple lines that will let me select values from the xml file, i.e.
String a = xmlDoc.SelectSingleNode(#"/Research/Product/Content/Title").Value;
BTW, I have no (direct) control over the XML file content.
I don't believe you can use an empty namespace alias and have it used automatically by the XPath expression. As soon as you use an actual alias, it should work though. This test is fine, for example:
using System;
using System.Xml;
using System.Xml.XPath;
class Test
{
static void Main()
{
string xmlFile = "test.xml";
XPathDocument xmldoc = new XPathDocument(xmlFile);
XPathNavigator nav = xmldoc.CreateNavigator();
XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable);
nsMgr.AddNamespace("x", "http://www.rixml.org/2005/3/RIXML");
XPathNavigator result = nav.SelectSingleNode("/x:Research", nsMgr);
Console.WriteLine(result);
}
}
Do you have to use XPath and XPathDocument, by the way? I tend to find that LINQ to XML is a much more pleasant API, particularly when it comes to namespaces. If you're using .NET 3.5 and you have no particular requirement to use XPath, I'd suggest you check it out.
Make the following changes
nsMgr.AddNamespace("x", "http://www.rixml.org/2005/3/RIXML");
XPathNavigator result = nav.SelectSingleNode("/x:Research", nsMgr);
i could post, and answer my own question, for the native equivalent of this code. Instead i'll just add it as an answer to the end.
When using the native IXMLDOMDocument (version 6) object:
//Give the default namespace as alias of "x"
document.setProperty("SelectionNamespaces","xmlns:x='http://www.rixml.org/2005/3/RIXML'");
//Query for the nodes we want
document.selectSingleNode("/x:Research");
Bonus Question: Why, oh why, does no Xml Document object model query the default namespace when no namespace is specified... sigh

Categories

Resources