Problem in iterating sharepoint folder content - c#

I am trying to access Folder from Document Library using web services in C#.
I am using SiteData's EnumerateFolder() method to get sub folders and files. But the method gives me only 3 properties for each entry.
IsFolder
Url
Last modified date
So how can we get 'Modified By' field value.
Or there is another solution for enumerating folders and subfolders.
Thanks.

You need to use the List API in order to get more properties from your objects.
[Edit - complete code sample]
The sample needs to be cleaned up, but should give you what you need
public void SomeFunction()
{
Lists lists = new Lists(); //http://server/_vti_bin/Lists.asmx
XmlNode coll = lists.GetListCollection();
XmlNamespaceManager nsMgr = new XmlNamespaceManager(coll.OwnerDocument.NameTable);
nsMgr.AddNamespace("sp", "http://schemas.microsoft.com/sharepoint/soap/");
nsMgr.AddNamespace("z", "#RowsetSchema");
XmlDocument xmlDoc = new XmlDocument();
XmlElement query = xmlDoc.CreateElement("Query");
XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");
viewFields.InnerXml = "<FieldRef Name=\"Modified_x0020_By\" />";
queryOptions.InnerXml = "<ViewAttributes Scope=\"RecursiveAll\"/>";
XmlNodeList siteLists = coll.SelectNodes("//sp:List", nsMgr);
foreach (XmlNode list in siteLists)
{
if (list.Attributes["ServerTemplate"].Value != "101") continue; //101=DocLib
XmlNode listItemCollection = lists.GetListItems(list.Attributes["Name"].Value, string.Empty, query,
viewFields, "4000",
queryOptions, null);
XmlNodeList listItems = listItemCollection.SelectNodes("//z:row", nsMgr);
foreach (XmlNode listItem in listItems)
{
if (listItem.Attributes["ows_FSObjType"] == null) continue;
if (!listItem.Attributes["ows_FSObjType"].Value.EndsWith("#1")) continue;
PrintModifiedBy(listItem);
}
}
}
private void PrintModifiedBy(XmlNode listItem)
{
string modifiedBy;
if (listItem.Attributes["Modified_x0020_By"] != null)
modifiedBy = listItem.Attributes["ows_Modified_x0020_By"].Value;
else
modifiedBy = listItem.Attributes["ows_Editor"].Value;
Console.WriteLine(modifiedBy);
}

Related

Can't get XML node when using namespace

I looked everywhere and can't read the value of an XML node that has a namespace prefix when using the namespace manager.
XmlDocument rssXmlDoc = new XmlDocument();
rssXmlDoc.Load("https://www.kijiji.ca/rss-srp-batterie-percussion/quebec/c612l9001");
StringBuilder rssContent = new StringBuilder();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(rssXmlDoc.NameTable);
nsmgr.AddNamespace("dc", #"http://schemas.microsoft.com/office/infopath/2003/myXSD/2005-08-25T08-37-41");
nsmgr.AddNamespace("g-core", #"http://schemas.microsoft.com/office/infopath/2003/myXSD");
XmlNodeList rssNodes = rssXmlDoc.SelectNodes("rss/channel/item");
// Iterate through the items in the RSS file
foreach (XmlNode rssNode in rssNodes)
{
String itemsForList = "";
XmlNode rssSubNodeTitle = rssNode.SelectSingleNode("title");
XmlNode rssSubNodePrice = rssNode.SelectSingleNode("g-core:price", nsmgr);
if (rssSubNodeTitle != null && rssSubNodeTitle.InnerText != "")
{
itemsForList = rssSubNodeTitle.InnerText;
if (rssSubNodePrice != null) { itemsForList += " (" + rssSubNodePrice.InnerText + ")"; }
}
listBox1.Items.Add(WebUtility.HtmlDecode(itemsForList));
}
The URI for the g-core namespace was wrong. It works for me when corrected to the following:
nsmgr.AddNamespace("g-core", #"http://base.google.com/ns/1.0");
When debugging these things it's helpful to save the XML to a local file and examine it in Visual Studio, Code, etc.

XML element not displaying for empty values

I am using an xml file to import into the database using the below code
CS:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(pathPMO + "Data.xml");
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/DocumentElement/Profile");
bool insertProfile = false;
foreach (XmlNode node in nodeList)
{
strYear = node.SelectSingleNode("Profile_x0020_Year").InnerText;
strID = node.SelectSingleNode("Profile_x0020_ID").InnerText;
strLead = node.SelectSingleNode("Profile_x0020_Leader").InnerText;
insertProfile = ImportProfile(strYear, strID, strLead);
}
For instance the profile leader values are empty for certain rows and when I try to insert them I get an error object not set to an instance of an object because of that particular element missing in few rows.
Can anyone suggest how to solve this?
You should ensure that each XmlNode object is not null. You can use a simple method like that:
private string GetXmlNodeString(string nodeName, XmlNode node)
{
if(String.IsNullOrWhiteSpace(nodeName))
return String.Empty;
var singleNode = node.SelectSingleNode(nodeName);
if(singleNode ==null)
return String.Empty;
return singleNode.InnerText;
}
then change your code like that:
foreach (XmlNode node in nodeList)
{
strYear = GetXmlNodeString("Profile_x0020_Year",node);
strID = GetXmlNodeString("Profile_x0020_ID",node);
strLead = GetXmlNodeString("Profile_x0020_Leader",node);
insertProfile = ImportProfile(strYear, strID, strLead);
}

how to get the value from innerXMl correctly

I plan to retrieve each suggestion in array and then stroe it in to the list. I have trouble retrieve the option node data, in this pattern {aeroplane,aeroplanes, aerobian} {i}, Any kind soul can help me out with it.
XmlDocument findStringDoc = new XmlDocument();
findStringDoc.Load (Application.dataPath+ "/" + filename);
XmlNodeList nodeList = findStringDoc.SelectNodes("/results/error");
//XmlNodeList suggestionNodeList = findStringDoc.SelectNodes("/results/error/suggestions/option");
foreach(XmlNode xn in nodeList){
errorString.Add(xn["string"].InnerText);
errorType.Add(xn["type"].InnerText);
//string temp = xn["suggestion"].InnerXml;
////TODO: Retrieve suggestions here!
XmlNodeList suggestionNodeList = findStringDoc.SelectNodes("/suggestions");
foreach(XmlNode yn in suggestionNodeList){
option[suggestionNodeList.Count] = yn["option"].InnerText;
Debug.Log(yn["option"].InnerText);
}
suggestionResult.Add (option);
//Debug.Log(suggestionResult);
//XmlNodeList suggestionNodeList = findStringDoc.SelectNodes("/results/error[string='{0}']/suggestions/option",errorString[i]);
}
<results>
<error>
<string>aeroplan</string>
<description>Spelling</description>
<precontext>a</precontext>
<suggestions>
<option>aeroplane</option>
<option>aeroplanes</option>
<option>aerobian</option>
</suggestions>
<type>spelling</type>
</error>
<error>
<string>i</string>
<description>Make I uppercase</description>
<precontext></precontext>
<suggestions>
<option>I</option>
</suggestions>
<type>grammar</type>
<url>http://service.afterthedeadline.com/info.slp?text=i&tags=PRP&engine=1</url>
</error>
</results>
You can use my code below:
private static void GetSuggestionOption(string filename, string value, string optionSuggest)
{
XDocument xDoc = XDocument.Parse(filename);
var parentNode = xDoc.Descendants().Where(x => x.Value == value).Ancestors().FirstOrDefault();
var childNode = parentNode.Descendants().Where(x => x.Name == optionSuggest);
childNode.ToList().ForEach(x => Console.WriteLine(x.Value));
}
Calling: GetSuggestionOption(fileName, "aeroplan", "option");
Happy Coding!
You can use XmlDocument.SelectNodes() method passing suitable XPath string parameter to select specific element(s) from XmlDocument, for example :
public void GetSuggestionOption(string keyword)
{
XmlDocument doc = new XmlDocument();
doc.Load (Application.dataPath+ "/" + filename);
string xpath = string.Format("//error[string='{0}']/suggestions/option", keyword);
XmlNodeList optionSuggestionList = doc.SelectNodes(xpath);
foreach (XmlNode option in optionSuggestionList)
{
Debug.Log(option.InnerXml);
}
}
You can call the method this way for example : GetSuggestionOption("aeroplan")

C# : Modify a xml node

i have that xml file :
<?xml version="1.0" encoding="utf-8"?>
<reminders>
<reminder>
<Title>Alarm1</Title>
<Description>Desc1</Description>
<Time>03/07/2012 10:11AM</Time>
<snooze>1</snooze>
<repeat>None</repeat>
</reminder>
</reminders>
And i want to modify the innertext from Alarm1 to another value so i wrote that code which actually duplicate the entire node .
XmlDocument xml = new XmlDocument();
xml.Load("0.xml");
XmlNodeList elements = xml.SelectNodes("//reminders");
foreach (XmlNode element in elements)
{
if (element.InnerText == "Alarm1")
{
XmlNode newvalue = xml.CreateElement("MODIFIED");
element.ReplaceChild(newvalue, element);
xml.Save("0.xml");
}
}
And then tried another code :
foreach (XmlElement element in xml.SelectNodes("//reminder"))
{
if (element.InnerText == "Alarm1")
{
XmlNode newvalue = xml.CreateElement("MODIFIED");
element.ReplaceChild(newvalue, element);
xml.Save("0.xml");
}
}
But also doesn`t work....
EDIT 1 : [Figured out a new code]
XmlDocument xml = new XmlDocument();
xml.Load("0.xml");
foreach (XmlElement element in xml.SelectNodes("//reminder"))
{
foreach (XmlElement element1 in element)
{
if (element.SelectSingleNode("//Title").InnerText == "Alarm1")
{
XmlNode newvalue = xml.CreateElement("MODIFIED");
element.ReplaceChild(newvalue, element1);
xml.Save("0.xml");
}
}
}
But it made the Alarm1 becomes
<MODIFIED />
EDIT 2 : [I SOLVED IT :D]
Okay here is the code i could figure out :
XmlDocument xml = new XmlDocument();
xml.Load("0.xml");
foreach (XmlElement element in xml.SelectNodes("//reminder"))
{
foreach (XmlElement element1 in element)
{
if (element.SelectSingleNode("//Title").InnerText == "Alarm1")
{
MessageBox.Show(element1.InnerText);
XmlNode newvalue = xml.CreateElement("Title");
newvalue.InnerText = "MODIFIED";
element.ReplaceChild(newvalue, element1);
xml.Save("0.xml");
}
}
}
I`ll really appreciate your helps and thanks.
Try this:
xml.SelectSingleNode("//reminder/Title").InnerText = "NewValue";
Your foreach line is simply looping through a list of elements called "reminders", not it's child nodes.
Take a look at this xpath tutorial for more information:
http://www.w3schools.com/xpath/xpath_intro.asp
If you want to use linq with xml (I find it the best way) then you will want to use the System.Xml.Linq namespace. The classes in that namespace are all prefixed with just X not Xml. The functionality in this namespace is newer, better and much easier to manipulate with Linq.
var xml = XDocument.Load("0.xml");
var alarm1 = xml.Descendants("reminder")
.Single(r => r.Element("Title") == "Alarm1");
This code will give you a variable, alarm1 that is the reminder that has a title node of "Alarm1."
From that point its not clear to me exactly what you want to modify. If you just want to change the title then ...
alarm1.Element("Title").Value = "MODIFIED";
xml.Save("0.xml");
XDocument doc = XDocument.Load("0.xml");
IEnumerable<XElement> rech =
from el in doc.Root.Elements("reminder")
where (string)el.Element("Title") == "Alarm1"
select el;
if (rech.Count() != 0)
{
foreach (XElement el in rech)
{
el.Element("Title").SetValue("NEW TITLE");
}
}
doc.Save("0.xml");
XDocument xDoc = XDocument.Load(.....);
xDoc.Descendants("Title").First().Value = "New Value";
xDoc.Save(...)
XmlDocument xml = new XmlDocument();
xml.Load(...);
var newTitle = "MODIFIED";
var title_node = xml.GetElementsByTagName("Title");
if(!string.IsNullOrEmpty(newTitle) && title_node.Count > 0)
{
title_node[0].InnerText = newTitle;
}

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