I am requesting some data from an API as XML. First to GET id's and then POST the id's to a second endpoint to get the data in question.
The problem I'm having is to extract the id's and put them in a List like this one
List<string>() { "idxxxx", "idxxxx", "idxxxx", "idxxxx" } for the POST request body.
GET response (xmlStringResponse) looks like this
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><TaxeringsenhetsreferensResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:lmfault="http://namespace.lantmateriet.se/distribution/produkter/fault/v1" xmlns="http://namespace.lantmateriet.se/distribution/produkter/taxering/v2" xmlns:gml="http://www.opengis.net/gml/3.2"><Taxeringsenhetsreferens><id>553508-5</id><typ>Lantbruksenhet</typ></Taxeringsenhetsreferens><Taxeringsenhetsreferens><id>553511-5</id><typ>Specialenhet</typ></Taxeringsenhetsreferens><Taxeringsenhetsreferens><id>559405-5</id><typ>Industrienhet</typ></Taxeringsenhetsreferens><Taxeringsenhetsreferens><id>710531-4</id><typ>Industrienhet</typ></Taxeringsenhetsreferens></TaxeringsenhetsreferensResponse>
The code looks like this at this time and the idListXml is keep being empty. I'm doing something wrong here and cant figure it out..
XElement xmlTree = XElement.Parse(xmlStringResponse);
var idList = xmlTree.Descendants("Taxeringsenhetsreferens")
.Select(x => (string)x.Element("id"))
.ToList();
XElement requestBody = new XElement(ns + "IdRequest", idList.Select(l => new XElement(ns + "id", l)));
Thank you for your time!
Your code is good, you can just add the XNamespace, try the following code :
XElement xmlTree = XElement.Parse(xmlStringResponse);
XNamespace ns = "http://namespace.lantmateriet.se/distribution/produkter/taxering/v2";
var idList = xmlTree.Descendants(ns + "Taxeringsenhetsreferens")
.Select(x => x.Element(ns + "id").Value)
.ToList();
I hope this will help you get the expected result.
Related
Been studying Linq to XML, and so far I have been able to generate the following XML:
<?xml version="1.0" encoding="utf-8"?>
<_OCROUTPUT xmlns="http://whatever.com/output.xsd">
<_Payer>
<_Name>_Name1</_Name>
<_Address1>_Address11</_Address1>
<_Address2>_Address21</_Address2>
<_City>_City1</_City>
<_State>_State1</_State>
<_ZipCode>_ZipCode1</_ZipCode>
</_Payer>
<_SPANNINGSERVICELINES>
<_ServiceDate>_ServiceDate1</_ServiceDate>
<_CptCode>_CptCode1</_CptCode>
<_Modifier>_Modifier1</_Modifier>
<_ServiceUnits>_ServiceUnits1</_ServiceUnits>
<_ServiceCharges>1</_ServiceCharges>
<_AllowedAmount>1</_AllowedAmount>
<_NonCoveredAmount>_NonCoveredAmount1</_NonCoveredAmount>
<_DeniedAmount>1</_DeniedAmount>
<_ReasonCode>_ReasonCode1</_ReasonCode>
<_PaymentAmount>1</_PaymentAmount>
<_ContractAllowance>1</_ContractAllowance>
<_Sequestration>1</_Sequestration>
<_Deductible>1</_Deductible>
<_Copay>1</_Copay>
<_CoInsurance>1</_CoInsurance>
<_PrimaryPayerPayment>1</_PrimaryPayerPayment>
</_SPANNINGSERVICELINES>
<_PATIENTDETAILS>
<_PatientAccNo>_PatientAccNo1</_PatientAccNo>
<_PatientName>_PatientName1</_PatientName>
<_HicNo>_HicNo1</_HicNo>
<_MedRecNo>_MedRecNo1</_MedRecNo>
<_SERVICELINES>
<_ServiceDate>_ServiceDate1</_ServiceDate>
<_CptCode>_CptCode1</_CptCode>
<_Modifier>_Modifier1</_Modifier>
<_ServiceUnits>_ServiceUnits1</_ServiceUnits>
<_ServiceCharges>1</_ServiceCharges>
<_AllowedAmount>1</_AllowedAmount>
<_NonCoveredAmount>_NonCoveredAmount1</_NonCoveredAmount>
<_DeniedAmount>1</_DeniedAmount>
<_ReasonCode>_ReasonCode1</_ReasonCode>
<_PaymentAmount>1</_PaymentAmount>
<_ContractAllowance>1</_ContractAllowance>
<_Sequestration>1</_Sequestration>
<_Deductible>1</_Deductible>
<_Copay>1</_Copay>
<_CoInsurance>1</_CoInsurance>
<_PrimaryPayerPayment>1</_PrimaryPayerPayment>
</_SERVICELINES>
</_PATIENTDETAILS>
<_PATIENTDETAILS>
<_PatientAccNo>_PatientAccNo2</_PatientAccNo>
<_PatientName>_PatientName2</_PatientName>
<_HicNo>_HicNo2</_HicNo>
<_MedRecNo>_MedRecNo2</_MedRecNo>
<_SERVICELINES>
<_ServiceDate>_ServiceDate4</_ServiceDate>
<_CptCode>_CptCode4</_CptCode>
<_Modifier>_Modifier4</_Modifier>
<_ServiceUnits>_ServiceUnits4</_ServiceUnits>
<_ServiceCharges>0.9</_ServiceCharges>
<_AllowedAmount>0.9</_AllowedAmount>
<_NonCoveredAmount>_NonCoveredAmount4</_NonCoveredAmount>
<_DeniedAmount>0.9</_DeniedAmount>
<_ReasonCode>_ReasonCode4</_ReasonCode>
<_PaymentAmount>0.9</_PaymentAmount>
<_ContractAllowance>0.9</_ContractAllowance>
<_Sequestration>0.9</_Sequestration>
<_Deductible>0.9</_Deductible>
<_Copay>0.9</_Copay>
<_CoInsurance>0.9</_CoInsurance>
<_PrimaryPayerPayment>0.9</_PrimaryPayerPayment>
</_SERVICELINES>
</_PATIENTDETAILS>
<_PATIENTDETAILS>
<_PatientAccNo>_PatientAccNo3</_PatientAccNo>
<_PatientName>_PatientName3</_PatientName>
<_HicNo>_HicNo3</_HicNo>
<_MedRecNo>_MedRecNo3</_MedRecNo>
<_SERVICELINES>
<_ServiceDate>_ServiceDate7</_ServiceDate>
<_CptCode>_CptCode7</_CptCode>
<_Modifier>_Modifier7</_Modifier>
<_ServiceUnits>_ServiceUnits7</_ServiceUnits>
<_ServiceCharges>50.5</_ServiceCharges>
<_AllowedAmount>50.5</_AllowedAmount>
<_NonCoveredAmount>_NonCoveredAmount7</_NonCoveredAmount>
<_DeniedAmount>50.5</_DeniedAmount>
<_ReasonCode>_ReasonCode7</_ReasonCode>
<_PaymentAmount>50.5</_PaymentAmount>
<_ContractAllowance>50.5</_ContractAllowance>
<_Sequestration>50.5</_Sequestration>
<_Deductible>50.5</_Deductible>
<_Copay>50.5</_Copay>
<_CoInsurance>50.5</_CoInsurance>
<_PrimaryPayerPayment>50.5</_PrimaryPayerPayment>
</_SERVICELINES>
</_PATIENTDETAILS>
</_OCROUTPUT>
What I need to do now, is add additional _SERVICELINES under a specific Patient. So for example, if I had another set of data for a new _SERVICELINES, how would I go about say, adding it under _PatientAccNo2?
I'm assuming I need to do a Linq query to isolate _PatientAccNo2, then add the new node and its elements. I just can't seem to figure out how to do that.
This is the query I've come up with (don't yet know if it's correct):
XElement root = XElement.Load(filename)
IEnumerable<XElement> patientDetails =
from patient in root.Elements("_PATIENTDETAILS")
where (string)patient.Element("_PatientName") == "_PatientAccNo2"
select patient;
but after that I'm not sure how to proceed
Thank you in advance!
Try :
XDocument doc = XDocument.Load(FILENAME);
XNamespace ns = doc.Root.GetDefaultNamespace();
XElement patient = doc.Descendants(ns + "_PATIENTDETAILS").ToList().Where(x => (string)x.Element(ns + "_PatientAccNo") == "_PatientAccNo2").FirstOrDefault();
XElement serviceLines = patient.Element(ns + "_SERVICELINES");
serviceLines.Add(new XElement(ns + "New_Element", "123456789"));
I am working with a soap response form a wcf service and wish to extract the values form the individual elements. So far I am able to get the list of values from the soap envelope using:
XDocument xDoc = XDocument.Parse(ServiceResult);
List<XElement> ResultsView = xDoc.Descendants()
.Where(x => x.Name.LocalName == "ResultsView")
.ToList();
This gives me the results list:
<a:ResultsView>
<a:Duration>4032</a:Duration>
<a:Metres>41124</a:Metres>
<a:Status>Ok</a:Status>
</a:ResultsView>
I have not been able to get the individual results by querying the ResultsView I can get all the values in a single string which is of no use. Can you suggest a method that will get the values?
The full soap envelope returned is:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetLocalDataResponse xmlns="http://tempuri.org/">
<GetLocalDataResult xmlns:a="http://schemas.datacontract.org/2004/07/LocalWcf"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:ResultsView>
<a:Duration>4032</a:Duration>
<a:Metres>41124</a:Metres>
<a:Status>Ok</a:Status>
</a:ResultsView>
</GetLocalDataResult></GetLocalDataResponse></s:Body></s:Envelope>
I have tried a few different methods to extract the values mainly using linq like:
var results = ResultsView.Select(x => new
{
ResultsView = (string)x.Element("Duration"),
duration = x.Element("Duration")
});
The problem is that you're asking for an element without the namespace. If you use the right namespace, you don't need to check for local names or anything like that:
XNamespace ns = "http://schemas.datacontract.org/2004/07/LoacalWcf";
XDocument doc = XDocument.Parse(ServiceResult);
XElement resultsView = doc.Descendants(ns + "ResultsView").Single();
XElement duration = resultsView.Element(ns + "Duration");
Note the use of the + operator to create an XName from an XNamespace and a string.
(It looks like you may well then want to cast duration to int rather than string to get the value in a semantically-useful form.)
I'm trying to sort the date-tags in my XML by value:
var noteElements = xDoc.Root.Descendants("Note").OrderBy(o => (DateTime)o.Element("date")).ToList();
foreach (XElement noteEl in noteElements)
{
string noteDateValue = noteEl.Element("date").Value;
noteEl.ReplaceWith(new XElement("notedate", noteEl, new XAttribute("date", noteDateValue)));
}
That doesn't work. The dates are not sorted as expected.
XML:
<Root>
<Notes>
<notedate date="date here"><Note>
<date>1997-07-04T00:00:00</date>
</Note></notedate>
<notedate date="date here"><Note>
<date>1997-06-04T00:00:00</date>
</Note></notedate>
</Notes>
</Root>
Anyone who can explain what I'm doing wrong?
You're replacing each Note element with a notedate element. The order in which you perform that replacement is irrelevant.
It sounds like you actually want something like:
var notes = doc.Root.Element("Notes");
notes.ReplaceNodes(notes.Elements()
.OrderBy(x => (DateTime) x.Element("date"))
.Select(x => new XElement("notedate",
new XAttribute("date", "date here"),
x));
I did some searching around the web and could not find the cause of my problem so I apologize if that has already been asked in another form I just did not understand.
My problem is that I am trying to parse the XML retrieved from Yahoo! Fantasy Sports but nothing seems to be working.
I have converted the XML I received (using a GET request with my credentials) into a string. Here it is for evaluation.
<?xml version="1.0" encoding="UTF-8" ?>
- <fantasy_content xml:lang="en-US" yahoo:uri="http://fantasysports.yahooapis.com/fantasy/v2/game/223/players" xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" time="5489.1560077667ms" copyright="Data provided by Yahoo! and STATS, LLC" refresh_rate="60" xmlns="http://fantasysports.yahooapis.com/fantasy/v2/base.rng">
- <game>
<game_key>223</game_key>
<game_id>223</game_id>
<name>Football PLUS</name>
<code>pnfl</code>
<type>full</type>
<url>http://football.fantasysports.yahoo.com/f2</url>
<season>2009</season>
- <players count="25">
- <player>
<player_key>223.p.8261</player_key>
<player_id>8261</player_id>
- <name>
<full>Adrian Peterson</full>
<first>Adrian</first>
<last>Peterson</last>
<ascii_first>Adrian</ascii_first>
<ascii_last>Peterson</ascii_last>
</name>
<editorial_player_key>nfl.p.8261</editorial_player_key>
<editorial_team_key>nfl.t.16</editorial_team_key>
<editorial_team_full_name>Minnesota Vikings</editorial_team_full_name>
<editorial_team_abbr>Min</editorial_team_abbr>
- <bye_weeks>
<week>9</week>
</bye_weeks>
<uniform_number>28</uniform_number>
<display_position>RB</display_position>
- <headshot>
<url>http://l.yimg.com/iu/api/res/1.2/7gLeB7TR77HalMeJv.iDVA--/YXBwaWQ9eXZpZGVvO2NoPTg2MDtjcj0xO2N3PTY1OTtkeD0xO2R5PTE7Zmk9dWxjcm9wO2g9NjA7cT0xMDA7dz00Ng--/http://l.yimg.com/j/assets/i/us/sp/v/nfl/players_l/20120913/8261.jpg</url>
<size>small</size>
</headshot>
<image_url>http://l.yimg.com/iu/api/res/1.2/7gLeB7TR77HalMeJv.iDVA--/YXBwaWQ9eXZpZGVvO2NoPTg2MDtjcj0xO2N3PTY1OTtkeD0xO2R5PTE7Zmk9dWxjcm9wO2g9NjA7cT0xMDA7dz00Ng--/http://l.yimg.com/j/assets/i/us/sp/v/nfl/players_l/20120913/8261.jpg</image_url>
<is_undroppable>1</is_undroppable>
<position_type>O</position_type>
- <eligible_positions>
<position>RB</position>
</eligible_positions>
<has_player_notes>1</has_player_notes>
</player>
- <player>
</players>
</game>
</fantasy_content>
The two methods I have tried are these (PLEASE NOTE: "xmlContent" is the string that contains the XML listed above):
1.)
XDocument chicken = XDocument.Parse(xmlContent);
var menus = from menu in chicken.Descendants("name")
select new
{
ID = menu.Element("name").Value,
};
and
2.)
byte[] encodedString = Encoding.UTF8.GetBytes(xmlContent);
MemoryStream ms = new MemoryStream(encodedString);
XmlDocument doc = new XmlDocument();
doc.Load(ms);
foreach (XmlNode row in doc).SelectNodes("//fantasy_content"))
{}
Basically, I get no results enumerated. I have a feeling I am missing some key steps here though. Any help is greatly appreciated. Thank you all.
UPDATE:
As per the awesome suggestions I received, I tried three more things. Since it is not working still, I did not listen very well. :) Actually, that is semi-accurate, please bear with my newbie attempt at working with XML here as I really am thankful for the responses. Here is how I am screwing up the great suggestions, can you offer another tip on what I missed? Thank you all again.
As per Jon Skeet's suggestion (this yields no results for me):
1.) XNamespace ns = "http://fantasysports.yahooapis.com/fantasy/v2/base.rng";
XDocument chicken = XDocument.Parse(xmlContent);
var menus = from menu in chicken.Descendants(ns + "fantasy_content")
select new
{
ID = menu.Element("name").Value,
};
As per the second suggestion (this throws me an error):
2.) var result = XElement.Load(xmlContent).Descendants().Where(x => x.Name.LocalName == "name");
As per the combinations of suggesting I need to identify the namespace and Yahoo! guide at: http://developer.yahoo.com/dotnet/howto-xml_cs.html
3.) xmlContent = oauth.AcquirePublicData(rtUrl, "GET");
byte[] encodedString = Encoding.UTF8.GetBytes(xmlContent);
MemoryStream ms = new MemoryStream(encodedString);
XmlDocument doc = new XmlDocument();
doc.Load(ms);
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("fantasy_content", "http://fantasysports.yahooapis.com/fantasy/v2/base.rng");
XmlNodeList nodes = doc.SelectNodes("/name", ns);
foreach (XmlNode node in nodes)
{
}
This is what's tripping you up:
xmlns="http://fantasysports.yahooapis.com/fantasy/v2/base.rng"
You're asking for elements in the unnamed namespace - but the elements default to the namespace shown above.
It's easy to fix that in LINQ to XML (and feasible but less simple in XmlDocument)
XNamespace ns = "http://fantasysports.yahooapis.com/fantasy/v2/base.rng";
var menus = chicken.Descendants(ns + "name")
...
Note that in your original method you're actually looking for name elements within the name elements - that's not going to work, but the namespace part is probably enough to get you going.
EDIT: It's not clear why you're using an anonymous type at all, but if you really want all the name element values from the document as ID properties in anonymous type instances, just use:
XNamespace ns = "http://fantasysports.yahooapis.com/fantasy/v2/base.rng";
var menus = chicken.Descendants(ns + "name")
.Select(x => new { ID = x.Value });
Note that there's no need to use Descendants(ns + "fantasy_content") as that's just selecting the root element.
Element name consists of two parts: xmlns(namespace) and localname. If xmlns is absent, name is equal to local name. So, you have to create name with namespace or ignore it
You can ignore namespace in your LINQ, just use LocalName
var result = XElement.Load(#"C:\fantasy_content.xml")
.Descendants()
.Where(x => x.Name.LocalName == "name")
.ToList();
I have a data set that I receive from a service. The data comes in XML format. We are given an XElement object with all the data. The structure of the XML document is very simple. Looks like this:
<root>
<dataPoint>
<id>1</id>
<param1>somedata</param1>
<param2>somedata</param2>
</dataPoint>
<dataPoint>
<id>2</id>
<param1>somedata</param1>
<param2>somedata</param2>
</dataPoint>
</root>
Of course, I have a large number of dataPoints. I also have a list (List) with the id's of dataPoints being displayed in a GUI. What I'd like to have is the dataPoints that ARE NOT displayed on the GUI so I can manipulate only those and not the whole data set.
Thanks
var toDisplay = new List<string>() { "2" };
var xDoc = XElement.Load(.....);
var dPoints = xDoc.Descendants("dataPoint")
.Where(d => !toDisplay.Contains(d.Element("id").Value));
var newXml = new XElement("root",dPoints).ToString();
Here's one way using a mutable dictionary and giving you a dictionary of points and corresponding nodes:
var xml = "<root> \r\n <dataPoint>\r\n <id>1</id>\r\n <param1>somedata</param1>\r\n <param2>so" +
"medata</param2>\r\n </dataPoint>\r\n <dataPoint>\r\n <id>2</id>\r\n <param1>somedata" +
"</param1>\r\n <param2>somedata</param2>\r\n </dataPoint>\r\n</root>";
var doc = XElement.Parse(xml);
var pointsInGui = new List<int> {1, 3, 5};
var dict = doc.Descendants("dataPoint").ToDictionary(e => Convert.ToInt32(e.Element("id").Value));
foreach (var point in pointsInGui) dict.Remove(point);
At this point dict contains 2 => <relevant element>.