XML Reader – Reads XML files from PC and upload to SharePoint document library

Hello there,

In my last blog, we saw how to browse files from PC and upload it to SharePoint document library, check it here.

In today’s blog, we are going to see, how to upload files and also update metadata of the files to be uploaded to SharePoint document library by picking their names from .xml files which are stored in a folder on PC. Scenario is little bit similar to the scenario in the previous blog, just in this case we are not browsing files from PC but the folder path is given in the form of string. Let’s get started!

Prerequisites:

  1. SharePoint Online tenant.
  2. Visual Studio IDE.

Scenario:

  1. Name of folder from which files are to be uploaded – Demo Folder.
  2. .xml files names – File1.xml, File2.xml
  3. Files to be uploaded – File1.docx, File2.docx
  4. xml contains the name and metadata of File1.docx and File2.xml contains the name and metadata of File2.docx
  5. We are going to read File1.xml and File2.xml and get the names and metadata of file to be uploaded one by one.
  6. Important point to note here that .xml files are not to be uploaded.

Important Methods or Classes used:

  1. Class XmlTextReader :-
    1. It can read from a file, from an internet location, or from any other stream of data
    2. Parameter passed is string containing .xml file path
  2. Method SaveBinaryDirect():-
    1. Method with a FileStream object to upload files to a document library.
    2. Parameters passed are – client context object, server relative destination path, file stream object.
  3. Class StreamWriter:-
    1. Class used to write a file (In this case used for error logs).
  4. Detailed code is given below with comments to understand easily.

Code:

App.Config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<appSettings>
<add key="SiteURL" value="Provide Site Collection URL Here"/>
<add key="Username" value="Provide Username Here"/>
<add key="Password" value="Provide Password Here"/>
</appSettings>
</configuration>

Program.cs

using Microsoft.SharePoint.Client;
using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Security;
using System.Xml;
using System.Data;

namespace XMLReader
{
class Program
{
static void Main(string[] args)
{
#region Connect to SP site

//Read details from app.config file
string siteURL = ConfigurationManager.AppSettings["SiteURL"];
string userName = ConfigurationManager.AppSettings["UserName"];
string password = ConfigurationManager.AppSettings["Password"];

ClientContext clientContext = new ClientContext(siteURL);
SecureString securePassword = new SecureString();

//Formation of secure password string
foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);

clientContext.Credentials = new SharePointOnlineCredentials(userName, securePassword);

//Load the web
Web web = clientContext.Web;
clientContext.Load(web);
clientContext.ExecuteQuery();

#endregion
string foldername = "C:\\Books\\Blogs\\Demo Folder";
UploadFoldersRecursively(clientContext, foldername, "Documents");
}//static void Main(string[] args)

#region UploadDocument
/// <summary>
/// Method to upload document in the folder
/// </summary>
/// <param name="clientContext"></param>
/// <param name="sourceFilePath"></param>
/// <param name="serverRelativeDestinationPath"></param>
public static void UploadDocument(ClientContext clientContext, string sourceFilePath, string serverRelativeDestinationPath)
{
try
{
using (var fs = new FileStream(sourceFilePath, FileMode.Open))
{
var file = new FileInfo(sourceFilePath);
//Upload each document to the destination folder
Microsoft.SharePoint.Client.File.SaveBinaryDirect(clientContext, serverRelativeDestinationPath, fs, true);
}//using (var fs = new FileStream(sourceFilePath, FileMode.Open))
}//try
catch (Exception ex)
{
Console.WriteLine(ex.Message);
ErrorLog("UploadDocument", ex.Message, ex.StackTrace);
}
}//UploadDocument(ClientContext clientContext, string sourceFilePath, string serverRelativeDestinationPath)
#endregion

#region UploadFoldersRecursively
/// <summary>
/// Method to upload folder - Selected folder on PC gets created on SP site in Document library
/// </summary>
/// <param name="clientContext"></param>
/// <param name="sourceFolder"></param>
/// <param name="destinationLibraryTitle"></param>
public static void UploadFoldersRecursively(ClientContext clientContext, string sourceFolder, string destinationLibraryTitle)
{
try
{
//Load detination library
Web web = clientContext.Web;
var query = clientContext.LoadQuery(web.Lists.Where(p => p.Title == destinationLibraryTitle));
clientContext.ExecuteQuery();
List documentsLibrary = query.FirstOrDefault();
var folder = documentsLibrary.RootFolder;
DirectoryInfo dir = new DirectoryInfo(sourceFolder);

clientContext.Load(documentsLibrary.RootFolder);
clientContext.ExecuteQuery();

folder = documentsLibrary.RootFolder.Folders.Add(dir.Name);
clientContext.ExecuteQuery();

UploadFolder(clientContext, dir, folder);
Console.ReadLine();
}//try
catch (Exception ex)
{
Console.WriteLine(ex.Message);
ErrorLog("UploadFoldersRecursively", ex.Message, ex.StackTrace);
}
}//public static void UploadFoldersRecursively(ClientContext clientContext, string sourceFolder, string destinationLibraryTitle)
#endregion

#region UploadFolder
/// <summary>
/// Method to upload a folder - Uploads folder recursively
/// </summary>
/// <param name="clientContext"></param>
/// <param name="folderInfo"></param>
/// <param name="folder"></param>
public static void UploadFolder(ClientContext clientContext, DirectoryInfo folderInfo, Folder folder)
{
FileInfo[] files = null;
DirectoryInfo[] subDirs = null;

try
{
//Get all files from the folder
files = folderInfo.GetFiles("*.xml*");

if (files != null)
{
//Loop through each document and upload it separately
foreach (FileInfo file in files)
{
int flag = 0;
string attribType = "";
string fileNameForQuery = "";
XmlTextReader reader = new XmlTextReader("C:\\Books\\Blogs\\Demo Folder\\"+file.Name);
while (reader.Read())
{
string fileName = "";
switch (reader.NodeType)
{
case XmlNodeType.Element: // The node is an element. for e.g. <FileName>xyz.docx<FileName> where <FileName> is element
if (reader.Name == "Name")
flag = 1;
else {
flag = 2;
attribType = reader.Name;
}
Console.Write("<" + reader.Name);
Console.WriteLine(">");
break;
case XmlNodeType.Text: //Display the text in each element. for e.g.<FileName>xyz.docx<FileName> where xyz.docx is text
fileName = reader.Value.Replace("\r\n", "");
if (flag == 1)
{
clientContext.Load(folder);
clientContext.ExecuteQuery();
UploadDocument(clientContext, "C:\\D drive\\Books\\Blogs\\Demo Folder\\" + fileName, folder.ServerRelativeUrl + "/" + fileName);
fileNameForQuery = fileName;
}//if (reader.Name == "Name")
else
{
CamlQuery query = new CamlQuery();
//query.ViewXml = @"<View Scope = 'Recursive'><Query></Query></View>";
query.ViewXml = @"<View Scope = 'Recursive'><Query><Where><Eq><FieldRef Name='FileLeafRef'/>
<Value Type='File'>" + fileNameForQuery + "</Value></Eq></Where></Query><ViewFields><FieldRef Name = 'FileRef'/><FieldRef Name = 'FileLeafRef'/></ViewFields></View>";
query.FolderServerRelativeUrl = folder.ServerRelativeUrl;
List docs = clientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection items = docs.GetItems(query);
clientContext.Load(items);
clientContext.ExecuteQuery();
if (items.Count > 0)
{
switch (attribType)
{
case "Type":
foreach (ListItem item in items)
{
item["FileType"] = fileName;
item.Update();
}
break;
case "Size":
foreach (ListItem item in items)
{
item["FileSize"] = fileName;
item.Update();
}
break;
}//switch (fileName)
}//if (items.Count > 0)
}//else
break;
case XmlNodeType.EndElement: //Display the end of the element.
Console.Write("</" + reader.Name);
Console.WriteLine(">");
break;
}//switch (reader.NodeType)
}//while (reader.Read())
}//foreach (System.IO.FileInfo file in files)
}//if (files != null)
}//try
catch (Exception ex)
{
Console.WriteLine(ex.Message);
ErrorLog("UploadFolder", ex.Message, ex.StackTrace);
}
}//public static void UploadFolder(ClientContext clientContext, System.IO.DirectoryInfo folderInfo, Folder folder)
#endregion

public static void ErrorLog(string methodName, string errorMessage, string stackTrace)
{
string filePath = "C:\\ErrorLogs.txt";

using (StreamWriter sw = new StreamWriter(filePath, true))
{
sw.WriteLine("Method name: " + methodName + Environment.NewLine + "Error Message: " + errorMessage + Environment.NewLine + "Stack Trace: " + stackTrace + Environment.NewLine + "Date & Time: " + DateTime.Now.ToString());
sw.WriteLine(Environment.NewLine + "-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine);
}//using (StreamWriter sw = new StreamWriter(filePath, true))
}//public static void ErrorLog(string methodName, string errorMessag
}//class Program
}//namespace XMLReader

References:

https://msdn.microsoft.com/en-us/library/0ax3f4f3(v=vs.110).aspx

https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/upload-large-files-sample-app-for-sharepoint

Thanks for reading 🙂

Keep reading, share your thoughts, experiences. Feel free to contact us to discuss more. If you have any suggestion / feedback / doubt, you are most welcome.

Stay tuned on Knowledge-Junction, will come up with more such articles.

This site uses Akismet to reduce spam. Learn how your comment data is processed.