Combine two XMLDocuments rss - c#

I've got two rss feeds I would like to merge together to make one. I've actually managed to merge the two feeds together and place the items in correct place - however the data in each attribute, i.e. title contains title+link+description+author+pubDate - and that repeats for link, description, author and pubdate. Can someone help me dubug it please?
Object rssData = new object();
Cms.UI.CommonUI.ApplicationAPI AppAPI = new Cms.UI.CommonUI.ApplicationAPI();
rssData = AppAPI.ecmRssSummary(50, true, "DateCreated", 0, "");
Response.ContentType = "text/xml";
Response.ContentEncoding = System.Text.Encoding.UTF8;
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(rssData.ToString());
//************************************************************
// Obtain 5 data items from second list
Object rssData1 = new object();
Cms.UI.CommonUI.ApplicationAPI AppAPI1 = new Cms.UI.CommonUI.ApplicationAPI();
rssData1 = AppAPI1.ecmRssSummary(60, true, "DateCreated", 5, "");
XmlDocument xmlDocument1 = new XmlDocument();
xmlDocument1.LoadXml(rssData1.ToString());
XmlNodeList nl = xmlDocument1.SelectNodes("/rss/channel");
XmlNode root = nl[0]; //do I need this line?
foreach (XmlNode xnode1 in root.ChildNodes)
{
string title = xnode1.InnerText;
string link = xnode1.InnerText;
string desc = xnode1.InnerText;
string auth = xnode1.InnerText;
string pdate = xnode1.InnerText;
//Merge new nodes
node = xmlDocument.CreateNode(XmlNodeType.Element, "item", null);
//node.InnerText = "this is new node";
//create title node
XmlNode nodeTitle = xmlDocument.CreateElement("title");
nodeTitle.InnerText = title;
//create Link node
XmlNode nodeLink = xmlDocument.CreateElement("link");
nodeLink.InnerText = link;
XmlNode nodeDesc = xmlDocument.CreateElement("description");
nodeDesc.InnerText = desc;
XmlNode nodeAuthor = xmlDocument.CreateElement("author");
nodeAuthor.InnerText = auth;
XmlNode nodepubDate = xmlDocument.CreateElement("pubDate");
nodepubDate.InnerText = pdate;
//add to parent node
node.AppendChild(nodeTitle);
node.AppendChild(nodeLink);
node.AppendChild(nodeDesc);
node.AppendChild(nodeAuthor);
node.AppendChild(nodepubDate);
//add to elements collection
//xmlDocument.DocumentElement.AppendChild(node);
xmlDocument.DocumentElement.SelectNodes("/rss/channel")[0].AppendChild(node);
}
//********************************************
xmlDocument.Save(Response.Output);

As you rightly suspected, the problem is here:
string title = xnode1.InnerText;
string link = xnode1.InnerText;
string desc = xnode1.InnerText;
string auth = xnode1.InnerText;
string pdate = xnode1.InnerText;
No wonder that
the data in each attribute, i.e. title contains
title+link+description+author+pubDate - and that repeats for link,
description, author and pubdate.
You need to read the values of specific subelements of each node. Probably something like:
string title = xnode1["title"].InnerText;
etc.
See http://www.csharp-examples.net/xml-nodes-by-name/ for reference.

Konrad's answer is clear, but it might not work if there's nested tags within the title tag.
Say, <title> TEXT <tag1> OTHER_TEXT </tag1></title>
On my computer, it will return you a concatenation of TEXT and OTHER_TEXT.
This should work:
string title = xnode1["title"].FirstChild.Value;
FirstChild will get you the TEXT no matter whether there is other tags with the title or not.

Related

Child node is repeating, can't get it to work

i have an xml code that create an xml file and this works great however i am a bit confused on why one of the parent node still opens and it does not group by employee first ( the employee hours and workdays should only open up once as long as the employee id is the same and close at the end when all days have been created) see attached code `
// Create a new <Employees> element and add it to the root node
XmlElement Employees = xmlDoc.CreateElement("employees");
xmlDoc.DocumentElement.AppendChild(Employees);
// Create a new <staffingHours> element and add it to the root node
XmlElement parentNode = xmlDoc.CreateElement("CompanyHours");
// Set attribute name and value!
parentNode.SetAttribute("processType", "merge");
xmlDoc.DocumentElement.PrependChild(parentNode);
string catid = "";
string nurseCode = GridView1.Rows[0].Cells[0].Text;
foreach ( GridViewRow row in GridView1.Rows)
{
//first part of EMPLOYEES ELEMENTS AND CHILD ELEMENTS
string fromFormat = "MM/dd/yyyy";
string toFormat = "yyyy-MM-dd";
if (catid != row.Cells[0].Text)
{
XmlElement employee = xmlDoc.CreateElement("employee");
xmlDoc.DocumentElement.AppendChild(employee);
Employees.AppendChild(employee);
//create the element
XmlElement NurseId1 = xmlDoc.CreateElement("employeeId");
employee.AppendChild(NurseId1);
NurseId1.InnerText = row.Cells[0].Text;
XmlElement HireDate1 = xmlDoc.CreateElement("hireDate");
employee.AppendChild(HireDate1);
DateTime newdate = DateTime.ParseExact(row.Cells[6].Text, fromFormat, null);
HireDate1.InnerText = newdate.ToString(toFormat);//row.Cells[6].Text;
xmlDoc.DocumentElement.InsertAfter(Employees, xmlDoc.DocumentElement.LastChild);
}
XmlElement EmployeeHours = xmlDoc.CreateElement("EmployeeHours");
if (catid != row.Cells[0].Text)
{
XmlElement NurseId = xmlDoc.CreateElement("employeeId");
staffHours.AppendChild(NurseId);
NurseId.InnerText = row.Cells[0].Text;
}
XmlElement WorkDays = xmlDoc.CreateElement("workDays");
XmlElement WorkDay = xmlDoc.CreateElement("workDay");
//Third node and data source
XmlElement Date = xmlDoc.CreateElement("date");
WorkDay.AppendChild(Date);
DateTime converteddate = DateTime.ParseExact(row.Cells[1].Text,
fromFormat, null);
Date.InnerText = converteddate.ToString(toFormat);
XmlElement hourEntries = xmlDoc.CreateElement("hourEntries");
xmlDoc.DocumentElement.PrependChild(hourEntries);
WorkDay.AppendChild(hourEntries);
XmlElement HourEntry = xmlDoc.CreateElement("hourEntry");
xmlDoc.DocumentElement.PrependChild(HourEntry);
hourEntries.AppendChild(HourEntry);
//Fourth node and data source
XmlElement Hours = xmlDoc.CreateElement("hours");
HourEntry.AppendChild(Hours);
Hours.InnerText = row.Cells[2].Text;
XmlElement JobTitleCode = xmlDoc.CreateElement("jobTitleCode");
HourEntry.AppendChild(JobTitleCode);
JobTitleCode.InnerText = row.Cells[3].Text;
XmlElement payTypeCode = xmlDoc.CreateElement("payTypeCode");
HourEntry.AppendChild(payTypeCode);
payTypeCode.InnerText = row.Cells[4].Text;
staffHours.AppendChild(WorkDays);
WorkDays.AppendChild(WorkDay);
parentNode.AppendChild(EmployeeHours);
xmlDoc.DocumentElement.InsertAfter(parentNode,
xmlDoc.DocumentElement.LastChild);
catid = row.Cells[0].Text;}
now once this code runs it create the attached image but i don't want the highlighted lines repeating inside the same parent node...
[1]: https://i.stack.imgur.com/eirsv.png
My issue was the element was inside of my loop i needed a new set of eyes to look into this. Good catch Tamas Szabo. issue is resolved.

how to extract particular attribute from xml file using c#?

static void Main(string[] args)
{
WebClient _httpReq = new WebClient(); // to talk to the web only for get method
string response = _httpReq.DownloadString("https://open-ic.epic.com/FHIR/api/FHIR/DSTU2/Patient?family=Argonaut&given=Jason");
Console.WriteLine(response);\\prints the xml string fetched from FHIR provider EPIC
XmlDocument xml = new XmlDocument();
xml.LoadXml(response); // suppose that myXmlString contains "<Names>...</Names>"
XmlNodeList xnList = xml.SelectNodes("/entry/resource/patient/name");
// here code is trying to extract the name attribute
foreach (XmlNode xn in xnList)
{
string firstName = xn["family value"].InnerText;
string lastName = xn["given value"].InnerText;
Console.WriteLine("Name: {0} {1}", firstName, lastName);
//print the first name and last name of the patient
}
Console.ReadLine();
}
i do it like this:
XmlDocument MyDocument = new XmlDocument();
MyDocument.Load("...");
XmlNode MyNode = MyDocument.SelectSingleNode("/Node_Name");
foreach (XmlAttribute MyAttribute in MyNode.Attributes)
{
if (MyAttribute.Name == "Attribute_Name")
{
object Value = MyAttribute.Value;
break;
}
}
Review XPath. Once you start understanding it, you will find it efficient and easier to code than iterating through lists. It also lets you directly get the nodes/attributes you want.
Then the code would be something similar to
string attrVal = doc.SelectSingleNode("/entry/resource/patient/#name").Value;
Or you can Load XML in XMlDocument and You can fetch element and out of that element you can read specific atairbute,
XmlDocument doc = new XmlDocument();
doc.LoadXml("<reply success=\"true\">More nodes go here</reply>");
XmlElement root = doc.DocumentElement;
string s = root.Attributes["success"].Value;

Reading XML with a colon (:)

I'm trying to get the views of a video from the following XML document (https://gdata.youtube.com/feeds/api/videos?q=example), I'm able to get the link and the autor because there is no colon in the tag.
I'm trying to get yt:statistics but I've no idea how.
result = e.Result.Replace("xmlns='http://www.w3.org/2005/Atom' ", String.Empty);
XmlDocument doc = new XmlDocument();
doc.LoadXml(result);
XmlNodeList videos = doc.GetElementsByTagName("entry");
foreach (XmlNode video in videos)
{
XmlNode insideauthor = video.SelectSingleNode("author");
string videoId = video.SelectSingleNode("id").InnerText.Replace("http://gdata.youtube.com/feeds/api/videos/", String.Empty);
string author = insideauthor.SelectSingleNode("name").InnerText;
// Trying to get the views of a video of the search results
MessageBox.Show(video.SelectSingleNode("yt:statistics").Attributes["viewCount"].InnerText);
}
XmlNodeList videos = doc.GetElementsByTagName("entry");
foreach (XmlNode video in videos)
{
string videoId = video["id"].InnerText.Replace("http://gdata.youtube.com/feeds/api/videos/", String.Empty);
string author = video["author"]["name"].InnerText;
string views = video["yt:statistics"].Attributes["viewCount"].Value;
Console.WriteLine(videoId);
Console.WriteLine(author);
Console.WriteLine(views);
}

Inserting data at specific position in XML

I want to read an XML file and match tag </contrib-group> and write a string after this tag
string Final = File.ReadAllText(Npath);
string Oxml = path + "\\" + Oword + ".abs.xml";
if (File.Exists(Oxml))
{
StreamReader xml = new StreamReader(Oxml,Encoding.UTF8);
string xmltag = xml.ReadToEnd();
//File.OpenWrite(Oxml);
xml.Close();
StreamWriter write = new StreamWriter(Oxml, true, Encoding.UTF8);
Match tag = Regex.Match(xmltag, #"</contrib-group>");
if (tag.Success == true)
{
write.WriteLine(Environment.NewLine);
write.Write(Final);
}
}
So I need to write the string Final to the XML file called Oxml after the matched XML tag </contrib-group>
If you are willing to save the new content as a valid XML file which you can work with, you should use the XML classes for that approach, this should look like this (untested):
XmlDocument doc = new XmlDocument();
doc.Load("YourFile.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("contrib-group");
for (int i=0; i < elemList.Count; i++)
{
XmlNode xnode = elemList[i];
XmlNode xnodeParent = xnode.ParentNode;
XMLNode newNode = doc.CreateNode(XmlNodeType.Element, "NodeName", "");
newNode.InnerText = "ContentInsideTheNode";
xnodeParent.InsertAfter(newNode, xnode);
}
doc.Save("YourFile.xml");
If you only need to replace the string for other purposes than saving it where having a valid XML is not an issue you can just handle it as a string and use the String.Replace (String, String) Method
string searchedTag = #"</contrib-group>";
string tagAndNewContent = #"</contrib-group>" + newContent;
string fileContentString = File.ReadAllText("YourFile.xml");
string ouput = fileContentString.Replace(searchedTag, tagAndNewContent);

Sharepoint via web service : checking if item exists in list

Because Microsoft did not include a way to have unique constraints in sharepoint, this has to be done manually.
I am inserting items into a sharepoint list via a web service method.
How can I check if an existing list item already exists with the same field ID value?
I've learnt I should be using wsLists.getListitems web service method, but its not exactly "user friendly". MSDN documentation is again not really great at explaining what should be an easy thing to do.
private bool itemDoesntExist()
{
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Document><Query><Where><Contains><FieldRef Name=\"ID\" /><Value Type=\"Text\">" + this.ID + "</Value></Contains></Where></Query><ViewFields /><QueryOptions /></Document>");
XmlNode listQuery = doc.SelectSingleNode("//Query");
XmlNode listViewFields = doc.SelectSingleNode("//ViewFields");
XmlNode listQueryOptions = doc.SelectSingleNode("//QueryOptions");
XmlNode items = this.wsLists.GetListItems(this.ListName , string.Empty, listQuery, listViewFields, string.Empty, listQueryOptions, null);
if (items.ChildNodes[1].Attributes["ItemCount"].Value == "0")
{
return true;
}
else
{
return false;
}
}
Here's a procedure I wrote 2 years ago that pulls the ID of a document with a given filename... I think you could easily revise it to return true/false if a given ID exists in a list.
protected string GetDocumentID(Lists.Lists ls, string ListGUID, string FileName)
{
string strDocumentID = "-1";
string strViewGUID = "";
string strRowLimit = "50000";
XmlDocument xmlDoc = new XmlDocument();
XmlNode query = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode viewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode queryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
query.InnerXml = "";
viewFields.InnerXml = "";
queryOptions.InnerXml = "<IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls>";
System.Xml.XmlNode nodeListItems = ls.GetListItems(ListGUID, strViewGUID, query, viewFields, strRowLimit, queryOptions, null);
XmlDocument doc = new XmlDocument();
doc.LoadXml(nodeListItems.InnerXml);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("z", "#RowsetSchema");
nsmgr.AddNamespace("rs", "urn:schemas-microsoft-com:rowset");
foreach (XmlNode node in doc.SelectNodes("/rs:data/z:row", nsmgr))
{
if (node.Attributes["ows_LinkFilename"].Value == FileName)
{
strDocumentID = node.Attributes["ows_ID"].Value;
break;
}
}
return strDocumentID;
}
Here's the code that calls it...
Lists.Lists ls = new Lists.Lists();
ls.PreAuthenticate = true;
ls.Credentials = System.Net.CredentialCache.DefaultCredentials;
ls.Url = SharePointSiteURL + #"/_vti_bin/lists.asmx";
string DocID = GetDocumentID(ls, ListGUID, FileName);

Categories