I have this XML:
<?xml version="1.0" encoding="utf-8"?>
<!-- Report generated by xxx -->
<report AppKey="stuffs" AppId="123">
<physician name="AAA BBB">
....
<services>
<service id="1" diagnostic="345" />
<service id="2" diagnostic="253" />
<service id="3" diagnostic="585" />
....
</services>
</physician>
</report>
and this c# code
XmlDocument doc = new XmlDocument();
doc.Load(file);
XmlNodeList xnList = doc.SelectNodes("/report/physician/services/*");
My problem is that the xnList is always empty, I tried with "/report/*" which return 0, tried with "/report/physician/*" which returns the same, only "*" returns the entire xml file. What I want to do is to select every <service> and then get their attributes. I cant seem to find a way to get every service element, because my queries always return nothing.
Can you use LINQtoXML? In that case it should be as simple as:
var doc = XDocument.Load(file);
XNamespace ns = "http://www.cnas.ro/siui/2.0";
var nodes = doc.Root.Element(ns + "physician")
.Element(ns + "services")
.Elements(ns + "service");
You can also use Descendants which will take the matching nodes regardless of their position in the tree, like this:
var nodes = doc.Root.Descendants(ns + "service");
Either way, you will get an IEnumerable<XElement> that you can easily map.
N.B. remember to add using System.Xml.Linq; in your directives.
UPDATE:
For mapping to the attributes, it is a matter of opinions... I would go like this:
var services = from n in nodes
select new
{
Id = n.Attribute("id").Value,
Diagnostic = n.Attribute("diagnostic").Value
};
services will be an IEnumerable<AnonymousType> which you can then iterate on:
foreach (var service in services)
{
Console.WriteLine(service.Id + " - " + service.Diagnostic);
}
Remove the asterisk;
XmlNodeList xnList = doc.SelectNodes("/report/physician/services/service");
foreach (XmlNode service in xnList)
x = service.Attributes["id"].Value;
This should select all service elements, no matter where they are in the file:
XmlNodeList xnList = doc.SelectNodes("//service");
Click here to find more XPath expressions
The below XPath should work for you.
XmlNodeList xnList = doc.SelectNodes("/report/physician/services/service");
Related
I am trying to get a list of the Service IDs from the xml file below.
<Settings>
<SomeTag>Some inner text</SomeTag>
<Services ID="Downtown Location">
<Service ID="22923">Basic</Service>
<Service ID="22926">Basic + 2</Service>
<Service ID="22927">Basic + 3</Service>
<Service ID="22928">Basic + 4</Service>
<Service ID="22929">Basic + 5</Service>
</Services>
<MoreTags>
<ATag></ATag>
<ATag></ATag>
<ATag></ATag>
<ATag></ATag>
</MoreTags>
</Settings>
I have tried several methods I found on line but each one has had some sort of problem. This was my last attempt.
List<string> ServiceList = new List<string>();
XmlDocument xdoc = new XmlDocument();
xdoc.Load(AppDomain.CurrentDomain.BaseDirectory + #"\Settings.xml");
XmlNodeList nodes = xdoc.DocumentElement.SelectNodes("/Services/Service");
foreach (XmlNode node in nodes)
{
ServiceList.Add(node.Attributes["ID"].Value);
}
return ServiceList;
In this case the nodes has no items. I have tried several variations of SelectNodes but still have no items. Earlier I tried XDocument and a LINQ query. I would prefer to do it that way, but I have yet to find an example that collects the IDs.
To be begin with, I believe it was a typo that you missed out the closing "Settings" Tag. To capture the ID using Linq to Xml, you could use.
XElement xmlNode = XElement.Load(filePath);
var result = xmlNode.Descendants("Service").Select(x=>x.Attribute("ID").Value);
Sample Output
Here is an example with System.Xml.Linq:
static void Main(string[] args)
{
var xmldoc = System.Xml.Linq.XDocument.Load(#"YOUR FILE");
foreach (var name in xmldoc.Descendants("Services").Elements()
.Select(x => new { Name = x.Name, Value = x.Value, ID=x.Attribute("ID")
}))
{
Console.WriteLine(name.ID.Value);
}
Console.ReadLine();
}
OUTPUT:
22923
22926
22927
22928
22929
The fix is to remove the leading / in the XPath expression in this line
XmlNodeList nodes = xdoc.DocumentElement.SelectNodes("/Services/Service");
to give you
XmlNodeList nodes = xdoc.DocumentElement.SelectNodes("Services/Service");
An XPath expression beginning with / starts the search for matching elements from the root of the document. You however have navigated to the document element and want to start the search from there.
I have looked everywhere, and cannot find anything to help me.
I am writing a program that connects to a webservice and then the webservice sends an XML response. After the response is received I have to retrieve certain values from it, but this is where it gets tricky
Here is a snippet of the returned XML:
<?xml version="1.0"?>
<MobilePortalSellingCategoriesHierarchy xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Response xmlns="http://blabla.com/service/">Successful</Response>
<ResponseNumber xmlns="http://blabla.com/service/">0</ResponseNumber>
<SellingCategoriesHierarchy xmlns="http://tym2sell.com/PortalService/">
<Response>Successful</Response>
<ResponseNumber>0</ResponseNumber>
<SellingCategories>
<PortalSellingCategory>
<SellingCategoryId xsi:nil="true" />
<SellingCategoryName>category1</SellingCategoryName>
<DeliveryMethod />
<DeliveryMethodNumber>0</DeliveryMethodNumber>
<SellingCategories>
<PortalSellingCategory>
<SellingCategoryId xsi:nil="true" />
<SellingCategoryName>category1_Item</SellingCategoryName>
<DeliveryMethod />
<DeliveryMethodNumber>0</DeliveryMethodNumber>
<SellingCategories>
<PortalSellingCategory>
<SellingCategoryId>2</SellingCategoryId>
<SellingCategoryName>Item2</SellingCategoryName>
<DeliveryMethod>Display</DeliveryMethod>
<DeliveryMethodNumber>1</DeliveryMethodNumber>
<VoucherValue>0.00</VoucherValue>
<IsVariablePrice>true</IsVariablePrice>
<MinimumVoucherValue>1.00</MinimumVoucherValue>
<MaximumVoucherValue>1000.00</MaximumVoucherValue>
<VoucherValueIncrement>1.00</VoucherValueIncrement>
<AdditionalInputItems>
<PortalAdditionalInputItem>
<InputItemId>-1</InputItemId>
<Label>Value:</Label>
<IsNumericOnly>true</IsNumericOnly>
<MaximumLength>7</MaximumLength>
<Hidden>false</Hidden>
</PortalAdditionalInputItem>
<PortalAdditionalInputItem>
<InputItemId>4</InputItemId>
<Label>Mobile Number</Label>
<IsNumericOnly>true</IsNumericOnly>
<MaximumLength>15</MaximumLength>
<Hidden>false</Hidden>
</PortalAdditionalInputItem>
</AdditionalInputItems>
<TwoStep>false</TwoStep>
<SelectedIcon>SamplePicture</SelectedIcon>
<UnSelectedIcon>SamplePicture</UnSelectedIcon>
This repeats from the SellingCategories node just under Response for a couple of times.
Here is a Snippet of my code where I get the XML as string.
XmlDocument xml = new XmlDocument();
xml.LoadXml(receivedData);
XmlNodeList xnList = xml.SelectNodes("/MobilePortalSellingCategoriesHierarchy");
foreach (XmlNode xn in xnList)
{
string sellingCategoryName = xn["SellingCategoryName"].InnerText;
string SelectedIcon = xn["SelectedIcon"].InnerText;
string UnSelectedIcon = xn["UnSelectedIcon"].InnerText;
richTextBox1.AppendText(string.Format("Name: {0} {1} {2}", sellingCategoryName, SelectedIcon, UnSelectedIcon));
}
I have tried changing xml.SelectNodes("/MobilePortalSellingCategoriesHierarchy");
to
xml.SelectNodes("/MobilePortalSellingCategoriesHierarchy/SellingCategoriesHierarchy/SellingCategories/PortalSellingCategory");
I need to select each SellingCategoryName and list the SellingCategoryName(s) and all the other items underneath it.
I was hoping to get something in the lines of:
Category1
Category1_Item
Item2
SamplePicture
Sample Picture
Mine only reads the First Node and then returns "Successful" to me.
I havve also tried:
XElement root = XElement.Load("FilePath");
var sellingCategoryNames = from PortalSellingCategory in root.Elements("MobilePortalSellingCategoriesHierarchy")
where (string)PortalSellingCategory.Element("SellingCategoriesHierarchy").Element("SellingCategories").Element("PortalSellingCategory") != ""
select PortalSellingCategory;
foreach (var xEle in sellingCategoryNames)
{
richTextBox1.Text = (string)xEle;
}
Any help would be greatly appreciated.
What you are doing with
xml.SelectNodes("/MobilePortalSellingCategoriesHierarchy");
is selecting your root node, which is just one. Thats why you only get one item in your list back. Is the hierarchy important? I can see that PortalSellingCategory can also be inside another PortalSellingCategory. If not maybe you could try the following select:
xml.SelectNodes("//PortalSellingCategory");
This will search for every node named "PortalSellingCategory" in your response, no mather where in the hierarchy it is.
EDIT:
And yes, you should look out for the namespaces, sry for didnt seeing that.
If you like geeting all the nodes with XPath you must create a new NamespaceManager and at it to your selectNodes call:
XmlDocument xml = new XmlDocument();
xml.LoadXml(data);
XmlNamespaceManager ns = new XmlNamespaceManager(xml.NameTable);
ns.AddNamespace("ns", "http://tym2sell.com/PortalService/");
XmlNodeList xnList = xml.SelectNodes("//ns:PortalSellingCategory", ns);
I would use XElement instead of XMLDocument, and then use Linq to query or pick the elmements like: XElement xContact = ....
int contactno = (int?)xContact.Element("command").Element("contactperson").Attribute("contactpersonid") ?? -1;
if (xContact.Element("command").Element("contactperson").Element("name").Element("firstname") != null)
console.writeline(xContact.Element("command").Element("contactperson").Element("name").Element("firstname").Value);
var doc= new XmlDocument();
doc.Load("FilePath");
var nodeList = xml.GetElementsByTagName("PortalSellingCategory");
Hi,
It returns the collection of nodes, and you just have to query it to get needed informations.
Feel free to ask help if needed.
Dimitri.
My XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<something.logger>
<add key="LoggerId" value="8a2ff9ef-d144-4dcb-86d8-6ccaf44def20">
</add>
<add key="FederationId" value="00000000-0000-0000-0000-000000000000" />
</something.logger>
</configuration>
My code:
XmlDocument xml = new XmlDocument();
xml.Load(Some-Valid-Path);
XmlNodeList xnList = xml.SelectNodes("/configuration/something.logger");
I am trying to get the Guid (or value..) of value.
In the end i want to get the string "8a2ff9ef-d144-4dcb-86d8-6ccaf44def20"
Thanks !
Use # at the beginning of attribute name to reference an attribute in XPath. Then you need to cast each item in list as XmlAttribute :
XmlNodeList xnList = doc.SelectNodes("/configuration/something.logger/add[#key='LoggerId']/#value");
foreach (XmlAttribute n in xnList)
{
Console.WriteLine(n.Value);
}
Use /# to access attributes:
XmlNodeList xnList = xml.SelectNodes("/configuration/something.logger/add/#value");
<Report xmlns="Microsoft.SystemCenter.DataWarehouse.Report.Alert" xmlns:p1="w3.org/2001/XMLSchema-instance"; Name="Microsoft.SystemCenter.DataWarehouse.Report.Alert" p1:schemaLocation="Microsoft.SystemCenter.DataWarehou?Schema=True">
<Title>Alert Report</Title>
<Created>6/27/2013 9:32 PM</Created>
<StartDate>6/1/2013 9:29 PM</StartDate>
<EndDate>6/27/2013 9:29 PM</EndDate>
<TimeZone>(UTC)</TimeZone>
<Severity>Warning, Critical</Severity>
<Priority>Low, Medium, High</Priority>
<AlertTable>
<Alerts>
<Alert>
<AlertName></AlertName>
<Priority></Priority>
</Alert>
</Alerts>
</AlertTable>
</Report>
So I'm trying to pull down the list of nodes that appear under Alerts child. So /Report/AlertTable/Alerts.
I've done very similar before but in this format it is not working for some reason. Can someone point me out in the right direction?
XmlDocument Log = new XmlDocument();
Log.Load("test.xml");
XmlNodeList myLog = Log.DocumentElement.SelectNodes("//Report/AlertTable/Alerts");
foreach (XmlNode alert in myLog)
{
Console.Write("HERE");
Console.WriteLine(alert.SelectNodes("AlertName").ToString());
Console.WriteLine(alert.SelectNodes("Priority").ToString());
Console.Read();
}
EDIT:
One of the responses had me try to use a bunch of namespace with p1 but had no such luck.
EDIT:
Did not work either:
var name = new XmlNamespaceManager(log.NameTable);
name.AddNamespace("Report", "http://www.w3.org/2001/XMLSchema-instance");
XmlNodeList xml = log.SelectNodes("//Report:Alerts", name);
From a site:
nodename Selects all nodes with the name "nodename"
/ Selects from the root node
// Selects nodes in the document from the current node that match the selection no matter where they are
So I believe
"/AlertTable/Alerts"
would work, as that would be 'from the root node' as well as
"Report/AlertTable/Alerts"
XPath Site
Figured this sucker out.
It had to do with the namespace of "Microsoft.SystemCenter.DataWarehouse.Report.Alert". Changing this to anything but that won't read the XML properly.
XmlDocument log = new XmlDocument();
log.Load(#"C:\Users\barranca\Desktop\test.xml");
// XmlNodeList xml = log.SelectNodes("//ns1:Alerts");
var name = new XmlNamespaceManager(log.NameTable);
name.AddNamespace("ns1", "Microsoft.SystemCenter.DataWarehouse.Report.Alert");
XmlNodeList xml = log.SelectNodes("//ns1:Alert", name);
foreach (XmlNode alert in xml)
{
Console.Write("HERE");
XmlNode test = alert.SelectSingleNode("//ns1:AlertName",name);
string testing = test.InnerText;
Console.Write(testing);
}
I don't how to extract the values from XML document, and am looking for some help as I'm new to C#
I am using XmlDocument and then XmlNodeList for fetching the particular XML document
Here is my code
XmlNodeList XMLList = doc.SelectNodes("/response/result/doc");
And my XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<result>
<doc>
<long name="LoadID">494</long>
<long name="EventID">5557</long>
<str name="XMLData"><TransactionDate>2014-05-28T14:17:31.2186777-06:00</TransactionDate><SubType>tblQM2222Components</SubType><IntegerValue title="ComponentID">11111</IntegerValue></str></doc>
<doc>
<long name="LoadID">774</long>
<long name="EventID">5558</long>
<str name="XMLData"><TransactionDate>2014-05-28T14:17:31.2186777-06:00</TransactionDate><SubType>tblQM2222Components</SubType><IntegerValue title="ComponentID">11111</IntegerValue></str></doc>
</result>
</response>
In this i have to fetch every the XMLData data that is under every doc tag and i have to fetch last doc tag EventID.
var xml = XDocument.Parse(xmlString);
var docs = xml.Root.Elements("doc");
var lastDocEventID = docs.Last()
.Elements("long")
.First(l => (string)l.Attribute("name") == "EventID")
.Value;
Console.WriteLine ("Last doc EventId: " +lastDocEventID);
foreach (var doc in docs)
{
Console.WriteLine (doc.Element("str").Element("TransactionDate").Value);
}
prints:
Last doc EventId: 5558
2014-05-28T14:17:31.2186777-06:00
2014-05-28T14:17:31.2186777-06:00
You can use two XPath expressions to select the nodes you want. To answer each part of your question in turn:
To select all of the XMLData nodes:
XmlNodeList XMLList
= doc.SelectNodes("/response/result/doc/str[#name='XMLData']");
To select the last EventId:
XmlNode lastEventIdNode =
doc.SelectSingleNode("/response/result/doc[position() =
last()]/long[#name='EventID']");
If not all doc nodes are guaranteed to have an event id child node, then you can simply:
XmlNodeList eventIdNodes =
doc.SelectNodes("/response/result/doc[long[#name='EventID']]");
XmlNode lastNode = eventIdNodes[eventIdNodes.Count - 1];
That should give you what you've asked for.
Update;
If you want the XML data inside each strXml element, you can use the InnerXml property:
XmlNodeList xmlList
= doc.SelectNodes("/response/result/doc/str[#name='XMLData']");
foreach(XmlNode xmlStrNode in xmlList)
{
string xmlInner = xmlStrNode.InnerXml;
}
There's one result tag short in your xml.
Try using this. It's cleaner too imho
XmlNodeList docs = doc.SelectSingleNode("response").SelectSingleNode("result").SelectNodes("doc");
Then you can use a combination of SelectSingleNode, InnerText, Value to get the data from each XmlNode in your list.
For example if you want the EventID from the first doc tag:
int eventID = int.Parse(docs[0].SelectSingleNode("long[#name='EventID']").InnerText);