How to get data out of xml XDocument in C#? - c#

I have an XML file that I get via a web service. File looks like this:
<Z_STU_CRS_TRNS_DOC xmlns="http://testurl">
<Z_STATUS_CODE>0</Z_STATUS_CODE>
<Z_STATUS_MSG>Success</Z_STATUS_MSG>
<Z_STUDENT_ID_SUB_DOC xmlns="http://testurl">
<Z_STU_ID>000999999</Z_STU_ID>
</Z_STUDENT_ID_SUB_DOC>
<Z_CRSE_SUB_DOC xmlns="http://testurl">
<Z_COURSE xmlns="http://testurl">
<Z_CRSE_DATA>9999|199901|TEST|9999|1|S|Scuba Diving| |XX</Z_CRSE_DATA>
</Z_COURSE>
<Z_COURSE xmlns="testurl">
<Z_CRSE_DATA>9999|200001|TEST|999|3|A|English 101| |XX</Z_CRSE_DATA>
</Z_COURSE>
</Z_CRSE_SUB_DOC>
</Z_STU_CRS_TRNS_DOC>
I'm able to consume the service and check for errors but I'm having a tough time actually getting the data out of the XDocument xml file.
protected void webClient_DownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
{
errorLabel.Text =
"The transaction failed. If you feel that you have reached " +
"this in error, please contact the help desk at xxx-xxx-xxxx.";
errorLabel.Visible = true;
return;
}
XDocument xml = XDocument.Parse(e.Result);
XNamespace ns = "http://testurl";
//Look for error code from WS
var field = xml.Descendants(ns + "Z_STATUS_CODE").FirstOrDefault();
if (field != null)
{
if (Convert.ToInt32((string)field.Value) == 1)
{
errorLabel.Text =
"The transaction failed, due to an invalid student id. If you " +
"feel that you have reached this in error, please contact " +
"the help desk at xxx-xxx-xxxx.";
errorLabel.Visible = true;
return;
}
}
I tried many different ways but nothing seems to help. Can someone help?

I figured it out! Posting in case someone else has similar issue.
List<studentRecord> studentCourses = new List<studentRecord>();
XmlReader reader = xml.CreateReader();
// Get elements
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "Z_CRSE_DATA"))
{
reader.Read();
if (reader.NodeType == XmlNodeType.Text)
{
studentRecord stuRec = new studentRecord();
stuRec.rawData = reader.Value;
studentCourses.Add(stuRec);
}
}
}
reader.Close();

You could read the node list, and read the values of the nodes according to their name.
It takes a bit more work, as you have to work through all the nodes itself, but like this you could do it
class Program
{
static void Main(string[] args)
{
string xmldata = #"<Z_STU_CRS_TRNS_DOC xmlns=""http://testurl"">
<Z_STATUS_CODE>0</Z_STATUS_CODE>
<Z_STATUS_MSG>Success</Z_STATUS_MSG>
<Z_STUDENT_ID_SUB_DOC xmlns=""http://testurl"">
<Z_STU_ID>000999999</Z_STU_ID>
</Z_STUDENT_ID_SUB_DOC>
<Z_CRSE_SUB_DOC xmlns=""http://testurl"">
<Z_COURSE xmlns=""http://testurl"">
<Z_CRSE_DATA>9999|199901|TEST|9999|1|S|Scuba Diving| |XX</Z_CRSE_DATA>
</Z_COURSE>
<Z_COURSE xmlns=""testurl"">
<Z_CRSE_DATA>9999|200001|TEST|999|3|A|English 101| |XX</Z_CRSE_DATA>
</Z_COURSE>
</Z_CRSE_SUB_DOC>
</Z_STU_CRS_TRNS_DOC>";
string errorTag = "Z_STATUS_CODE",
statusTag = "Z_STATUS_MSG";
XDocument xml = XDocument.Parse(xmldata);
XNamespace ns = "http://testurl";
int errorCode = -1;
string statusMessage = string.Empty;
using (XmlReader reader = xml.CreateReader())
{
while (reader.Read())
{
if (reader.NodeType != XmlNodeType.Element)
{
continue;
}
if (!string.Equals(reader.Name, errorTag) &&
!string.Equals(reader.Name, statusTag))
{
continue;
}
string currentName = reader.Name;
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.EndElement)
{
break;
}
if (reader.NodeType != XmlNodeType.Text)
{
continue;
}
if (string.Equals(currentName, errorTag))
{
errorCode = int.Parse(reader.Value);
}
if (string.Equals(currentName, statusTag))
{
statusMessage = reader.Value;
}
break;
}
}
}
if (errorCode == -1)
{
// no tag found
Console.WriteLine("No tag found named: {0}", errorTag);
}
else if (errorCode == 0)
{
Console.WriteLine("Operation was a success!");
}
else
{
Console.WriteLine("Operation failed with error code {0}", errorCode);
}
if (!string.IsNullOrWhiteSpace(statusMessage))
{
Console.WriteLine("Status message: {0}", statusMessage);
}
Console.ReadLine();
}
}

Related

Comparing lines of string in one text file against another text file, and displaying an an error when a non-match occurs

I'm relatively new to C# and I'm trying to get my head around a problem that I believe should be pretty simple in concept, but I just cant get it.
I am currently, trying to display a message to the console when the program is run from the command line with two arguments, if a sequence ID does not exist inside a text file full of sequence ID's and DNA sequences against a query text file full of Sequence ID's. For example args[0] is a text file that contains 41534 lines of sequences which means I cannot load the entire file into memory.:
NR_118889.1 Amycolatopsis azurea strain NRRL 11412 16S ribosomal RNA, partial sequence
GGTCTNATACCGGATATAACAACTCATGGCATGGTTGGTAGTGGAAAGCTCCGGCGT
NR_118899.1 Actinomyces bovis strain DSM 43014 16S ribosomal RNA, partial sequence
GGGTGAGTAACACGTGAGTAACCTGCCCCNNACTTCTGGATAACCGCTTGAAAGGGTNGCTAATACGGGATATTTTGGCCTGCT
NR_074334.1 Archaeoglobus fulgidus DSM 4304 16S ribosomal RNA, complete sequence >NR_118873.1 Archaeoglobus fulgidus DSM 4304 strain VC-16 16S ribosomal RNA, complete sequence >NR_119237.1 Archaeoglobus fulgidus DSM 4304 strain VC-16 16S ribosomal RNA, complete sequence
ATTCTGGTTGATCCTGCCAGAGGCCGCTGCTATCCGGCTGGGACTAAGCCATGCGAGTCAAGGGGCTT
args[1] is a query text file with some sequence ID's:
NR_118889.1
NR_999999.1
NR_118899.1
NR_888888.1
So when the program is run, all I want are the sequence ID's that were not found in args[0] from args[1] to be displayed.
NR_999999.1 could not be found
NR_888888.1 could not be found
I know this probably super simple, and I have spent far too long on trying to figure this out by myself to the point where I want to ask for help.
Thank you in advance for any assistance.
You can try this.
It loads each file content and compare with each other.
static void Main(string[] args)
{
if ( args.Length != 2 )
{
Console.WriteLine("Usage: {exename}.exe [filename 1] [filename 2]");
Console.ReadKey();
return;
}
string filename1 = args[0];
string filename2 = args[1];
bool checkFiles = true;
if ( !File.Exists(filename1) )
{
Console.WriteLine($"{filename1} not found.");
checkFiles = false;
}
if ( !File.Exists(filename2) )
{
Console.WriteLine($"{filename2} not found.");
checkFiles = false;
}
if ( !checkFiles )
{
Console.ReadKey();
return;
}
var lines1 = System.IO.File.ReadAllLines(args[0]).Where(l => l != "");
var lines2 = System.IO.File.ReadAllLines(args[1]).Where(l => l != "");
foreach ( var line in lines2 )
if ( !lines1.StartsWith(line) )
{
Console.WriteLine($"{line} could not be found");
checkFiles = false;
}
if (checkFiles)
Console.WriteLine("There is no difference.");
Console.ReadKey();
}
This works, but it only processes the first line of the files...
using( System.IO.StreamReader sr1 = new System.IO.StreamReader(args[1]))
{
using( System.IO.StreamReader sr2 = new System.IO.StreamReader(args[2]))
{
string line1,line2;
while ((line1 = sr1.ReadLine()) != null)
{
while ((line2 = sr2.ReadLine()) != null)
{
if(line1.Contains(line2))
{
found = true;
WriteLine("{0} exists!",line2);
}
if(found == false)
{
WriteLine("{0} does not exist!",line2);
}
}
}
}
}
var saved_ids = new List<String>();
foreach (String args1line in File.ReadLines(args[1]))
{
foreach (String args2line in File.ReadLines(args[2]))
{
if (args1line.Contains(args2line))
{
saved_ids.Add(args2line);
}
}
}
using (System.IO.StreamReader sr1 = new System.IO.StreamReader(args[1]))
{
using (System.IO.StreamReader sr2 = new System.IO.StreamReader(args[2]))
{
string line1, line2;
while ((line1 = sr1.ReadLine()) != null)
{
while ((line2 = sr2.ReadLine()) != null)
{
if (line1.Contains(line2))
{
saved_ids.Add(line2);
break;
}
if (!line1.StartsWith(">"))
{
break;
}
if (saved_ids.Contains(line1))
{
break;
}
if (saved_ids.Contains(line2))
{
break;
}
if (!line1.Contains(line2))
{
saved_ids.Add(line2);
WriteLine("The sequence ID {0} does not exist", line2);
}
}
if (line2 == null)
{
sr2.DiscardBufferedData();
sr2.BaseStream.Seek(0, System.IO.SeekOrigin.Begin);
continue;
}
}
}
}

Using AdvancedSearch for Outlook with C# Returns Zero Results

I'm trying to search my inbox and all subfolders for a given string in the subject line. I found the following code online(https://www.add-in-express.com/creating-addins-blog/2012/05/31/outlook-search-csharp-vbnet/), but it returns zero results which is not the expected result.
I looked at the filter under view settings in outlook for a given search term that returns results in the outlook explorer and got this query: "http://schemas.microsoft.com/mapi/proptag/0x0037001f" LIKE '%Ticket%'
When I plug that in to the below code I likewise get zero results.
When I use LINQ to query those folders(LINQ is too slow to be a real solution here) I can get results so I'm guessing I'm making a syntactical error with advancedsearch. It is hard to find examples of usage on the web. I will appreciate anyone that can help me.
private Search RunAdvancedSearch(Outlook._Application OutlookApp, string wordInSubject)
{
string advancedSearchTag = "New Search";
string scope = "Inbox";
string filter = "\"urn:schemas:mailheader:subject\" LIKE '%"+ wordInSubject +"%'";
Outlook.Search advancedSearch = null;
Outlook.MAPIFolder folderInbox = null;
Outlook.MAPIFolder folderSentMail = null;
Outlook.NameSpace ns = null;
try
{
ns = OutlookApp.GetNamespace("MAPI");
folderInbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
folderSentMail = ns.GetDefaultFolder(
Outlook.OlDefaultFolders.olFolderSentMail);
scope = "\'" + folderInbox.FolderPath +
"\',\'" + folderSentMail.FolderPath + "\'";
advancedSearch = OutlookApp.AdvancedSearch(
scope, filter, true, advancedSearchTag);
System.Diagnostics.Debug.WriteLine(advancedSearch.Results.Count);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "An exception is thrown!");
}
finally
{
if (advancedSearch != null) Marshal.ReleaseComObject(advancedSearch);
if (folderSentMail != null) Marshal.ReleaseComObject(folderSentMail);
if (folderInbox != null) Marshal.ReleaseComObject(folderInbox);
if (ns != null) Marshal.ReleaseComObject(ns);
}
return advancedSearch;
}
I was not waiting long enough for the results. When AdvancedSearch(which runs in a separate thread) is finished it fires off an event called AdvancedSearchComplete. I had to tell the code to handle the event in order to wait for the search to complete.
In RunAdvancedSearch I do this in the Try with this:
Application.AdvancedSearchComplete += Application_AdvancedSearchComplete;
Here is the whole thing.
string advancedSearchTag = "MY FOOFOO Search";
//SEARCH Function
Search RunAdvancedSearch(Outlook.Application Application, string wordInSubject)
{
string scope = "Inbox";
string filter = "urn:schemas:mailheader:subject LIKE \'%" + wordInSubject + "%\'";
Outlook.Search advancedSearch = null;
Outlook.MAPIFolder folderInbox = null;
Outlook.MAPIFolder folderSentMail = null;
Outlook.NameSpace ns = null;
try
{
ns = Application.GetNamespace("MAPI");
folderInbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
folderSentMail = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderSentMail);
scope = "\'" + folderInbox.FolderPath + "\',\'" +
folderSentMail.FolderPath + "\'";
advancedSearch = Application.AdvancedSearch(
scope, filter, true, advancedSearchTag);
Application.AdvancedSearchComplete += Application_AdvancedSearchComplete;
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "An eexception is thrown");
}
finally
{
if (advancedSearch != null) Marshal.ReleaseComObject(advancedSearch);
if (folderSentMail != null) Marshal.ReleaseComObject(folderSentMail);
if (folderInbox != null) Marshal.ReleaseComObject(folderInbox);
if (ns != null) Marshal.ReleaseComObject(ns);
}
return advancedSearch;
}
//Handle AdvancedSearchComplete event
void Application_AdvancedSearchComplete(Outlook.Search SearchObject)
{
Outlook.Results advancedSearchResults = null;
Outlook.MailItem resultItem = null;
System.Text.StringBuilder strBuilder = null;
try
{
if (SearchObject.Tag == advancedSearchTag)
{
advancedSearchResults = SearchObject.Results;
System.Diagnostics.Debug.WriteLine("Count: " + advancedSearchResults.Count);
if (advancedSearchResults.Count > 0)
{
strBuilder = new System.Text.StringBuilder();
strBuilder.AppendLine("Number of items found: " +
advancedSearchResults.Count.ToString());
foreach (MailItem item in advancedSearchResults)
{
System.Diagnostics.Debug.WriteLine(item.Subject);
}
for (int i = 1; i <= advancedSearchResults.Count; i++)
{
resultItem = advancedSearchResults[i] as Outlook.MailItem;
if (resultItem != null)
{
strBuilder.Append("#" + i.ToString());
strBuilder.Append(" Subject: " + resultItem.Subject);
strBuilder.Append(" \t To: " + resultItem.To);
strBuilder.AppendLine(" \t Date: " +
resultItem.SentOn.ToString());
Marshal.ReleaseComObject(resultItem);
}
}
if (strBuilder.Length > 0)
System.Diagnostics.Debug.WriteLine(strBuilder.ToString());
else
System.Diagnostics.Debug.WriteLine(
"There are no Mail items found.");
}
else
{
System.Diagnostics.Debug.WriteLine("There are no items found.");
}
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "An exception is occured");
}
finally
{
if (resultItem != null) Marshal.ReleaseComObject(resultItem);
if (advancedSearchResults != null)
Marshal.ReleaseComObject(advancedSearchResults);
}
}
private void btnOutlookSrch_Click(object sender, EventArgs e)
{
Outlook.Application OLook = new Outlook.Application();
RunAdvancedSearch(OLook, "Hello?");
}
Your filter is working good, use Application:
private Search RunAdvancedSearch(Outlook.Application OutlookApp, string wordInSubject)
https://msdn.microsoft.com/en-us/library/office/microsoft.office.interop.outlook.application.aspx
Read about using _Application and Application in msdn "Remarks". There is very well written.

look in xml element and return next column?

the xDocument response returns:
<Result>
<Value>FAIL</Value>
<Message>Error in Cloud/Upload - No Client Account exists</Message>
</Result>
in my below code if .Equals(Fail) I wat to throw an error containing the
XDocument response = XDocument.Parse(infoAsString);
if (response.Root.Name.LocalName.Equals("Result"))
{
try
{
if (response.Root.Elements.Equals("FAIL"))
{
throw new Exception("Error:" + //Message from xml);
}
}
Here's how you can do it using your existing XDocument (notice my comment about your check for "FAIL"):
if (response.Root.Name.LocalName.Equals("Result"))
{
try
{
//response.Root.Elements.Equals("FAIL") won't do what you want, try this:
var val = response.Root.Element("Value").Value;
if (val == "FAIL")
{
throw new Exception("Error: " + response.Root.Element("Message").Value);
}
}
}
No need for try / catch if the response (once determined to be a <Result>) is guaranteed to have the XML structure you provided.
if (response.Root.Name.LocalName == "Result")
{
if (response.Root.Element("Value").Value == "FAIL")
{
throw new Exception("Error: " + response.Root.Element("Message").Value);
}
}
try this, if your response is XmlDocument:
response.SelectSingleNode("//Message").InnerText
If not would be a lot easier to use XmlDocument see below:
XmlDocument respDoc = new XmlDocument();
respDoc.LoadXml(xml_string);
if(respDoc.SelectSingleNode("//Value").InnerText.Trim() == "FAIL")
{
throw new Exception("Error:" + response.SelectSingleNode("//Message").InnerText);
}
Ofcouse if you want it with XDocument then use :
response.Root.Element("Message").Value

C# update - code reading/xml reader

What would I add to this so that if there is no update available a message box pops up saying no update? Although this is probably an easy fix, I've been working on a lot of updating systems lately, but I'm just stumped on it.
Version newVersion = null;
string url = "";
XmlTextReader reader = null;
try
{
string xmlURL = "URL";
reader = new XmlTextReader(xmlURL);
reader.MoveToContent();
string elementName = "";
if ((reader.NodeType == XmlNodeType.Element) &&
(reader.Name == "App"))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
elementName = reader.Name;
else
{
if ((reader.NodeType == XmlNodeType.Text) &&
(reader.HasValue))
{
switch (elementName)
{
case "version":
newVersion = new Version(reader.Value);
break;
case "url":
url = reader.Value;
break;
}
}
}
}
}
}
catch
{
}
finally
{
if (reader != null) reader.Close();
}
Version curVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
if (curVersion.CompareTo(newVersion) < 0)
{
string title = "New Update Avaliable";
string question = "Download Now?";
if (DialogResult.Yes == MessageBoxEx.Show(this, question, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
Process.Start(url);
}
}
Is something wrong with comparing curVersion to newVersion?
if (curVersion == newVersion) {
MessageBox.Show("No Update Needed");
} else if (curVersion.CompareTo(newVersion) < 0)
{
string title = "New Update Avaliable";
string question = "Download Now?";
if (DialogResult.Yes == MessageBoxEx.Show(this, question, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
Process.Start(url);
}
}

Why do I get the error DTD is not allowed on this document?

Heres the code:
// iBEC/iBSS -> SHSH Generator Tool
using System;
using System.Collections.Generic;
using System.Text;
namespace SHSH_Tool
{
public enum VersionMode
{
V3_0 = 0,
V3_0_1
}
class Program
{
static void PrintUsage()
{
Console.WriteLine("iBEC/iBSS to SHSH Tool");
Console.WriteLine("Usage: SHSH_Tool -tmpfiles X:\\Path\\To\\Tmp\\Directories -output X:\\Path\\To\\00.SHSH");
Console.WriteLine("Note: If you have files for 3.0.1, use the -301 switch.");
}
static void Main(string[] args)
{
VersionMode toolMode = VersionMode.V3_0;
string firmwareRootPath = null; // #"E:\Work\Dev\iPhone\iBEC_iBSS_Grabber";
string outputFilename = null; // #"E:\Work\Dev\svn\iPhone\SHSH_Tool\3.0.shsh";
string lastArg = null;
foreach (string arg in args)
{
if (arg == "-301")
{
toolMode = VersionMode.V3_0_1;
}
if (lastArg == "-tmpfiles")
{
firmwareRootPath = arg;
}
else if (lastArg == "-output")
{
outputFilename = arg;
}
lastArg = arg.ToLower();
}
if (firmwareRootPath == null || outputFilename == null)
{
PrintUsage();
return;
}
if (!System.IO.Directory.Exists(firmwareRootPath))
{
Console.WriteLine("Unable to open TMP directories path.");
PrintUsage();
return;
}
string restoreRamDiskToIgnore = "018-5304-002.dmg";
string manifestFilename = "BuildManifest.30.xml";
string shshTemplateFilename = "3.0.shsh.template";
if (toolMode == VersionMode.V3_0_1)
{
restoreRamDiskToIgnore = "018-5804-001.dmg";
manifestFilename = "BuildManifest.30.xml";
shshTemplateFilename = "3.0.1.shsh.template";
Console.WriteLine("Operating in 3.0.1 Mode");
}
else
{
Console.WriteLine("Operating in 3.0 Mode");
}
try
{
Console.WriteLine("Reading IPSW Manifest File...");
//System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(Util.ReadEmbeddedResource(manifestFilename));
BuildManifestReader manifestReader = new BuildManifestReader(manifestFilename);
Console.WriteLine("Found Manifest Files:");
foreach (BuildManifestItem manifestItem in manifestReader.ManifestItems.Values)
{
Console.WriteLine(" - Key: " + manifestItem.Key + " [Digest: " + manifestItem.PartialDigest + "]");
}
Console.WriteLine("Processing TMP files...");
string strECID = null;
string[] subdirs = System.IO.Directory.GetDirectories(firmwareRootPath);
foreach (string subdir in subdirs)
{
if (!(subdir.Contains("Per") && subdir.EndsWith(".tmp")))
continue;
Console.WriteLine(" - Entering directory: " + subdir);
ProcessSubdirectory(subdir, manifestReader, ref strECID);
}
// Process current directory
ProcessSubdirectory(firmwareRootPath, manifestReader, ref strECID);
bool blobsOK = true;
Console.WriteLine("Verifying BLOB Data...");
foreach (BuildManifestItem manifestItem in manifestReader.ManifestItems.Values)
{
if (manifestItem.BlobData == null && manifestItem.Path != restoreRamDiskToIgnore)
{
if (manifestItem.Found)
{
Console.WriteLine(" - ERROR: Invalid signed data for " + manifestItem.Path);
}
else
{
Console.WriteLine(" - ERROR: File not found for " + manifestItem.Path);
}
blobsOK = false;
}
}
if (blobsOK)
{
Console.WriteLine("Creating custom SHSH file...");
System.IO.StreamReader shshTemplateFileHdl = new System.IO.StreamReader(Util.ReadEmbeddedResource(shshTemplateFilename));
string shshTemplateFile = shshTemplateFileHdl.ReadToEnd();
foreach (BuildManifestItem manifestItem in manifestReader.ManifestItems.Values)
{
shshTemplateFile = shshTemplateFile.Replace("[BLOB-" + manifestItem.Path + "]", manifestItem.BlobData);
shshTemplateFile = shshTemplateFile.Replace("[DIGEST-" + manifestItem.Path + "]", manifestItem.PartialDigest);
}
System.IO.StreamWriter shshFileWriter = new System.IO.StreamWriter(outputFilename);
shshFileWriter.Write(shshTemplateFile);
shshFileWriter.Close();
if (toolMode == VersionMode.V3_0)
{
Console.WriteLine("Success! 3.0 SHSH File stored at " + outputFilename);
}
else if (toolMode == VersionMode.V3_0_1)
{
Console.WriteLine("Success! 3.0.1 SHSH File stored at " + outputFilename);
}
}
else
{
Console.WriteLine("There were errors while trying to create SHSH file.");
}
}
catch (System.Exception e)
{
Console.WriteLine("There were errors while trying to create SHSH file.");
Console.WriteLine("Diagnostic: " + e.Message + " " + e.StackTrace);
}
finally
{
Console.WriteLine("Complete.");
}
}
static bool ProcessSubdirectory(string subdir, BuildManifestReader manifestReader, ref string strECID)
{
foreach (BuildManifestItem manifestItem in manifestReader.ManifestItems.Values)
{
if (manifestItem.BlobData != null)
continue;
string path = manifestItem.Path.Replace("/", "\\");
string searchPath = subdir + "\\" + path;
if (System.IO.File.Exists(searchPath))
{
Console.WriteLine(" - " + manifestItem.Path);
if (!ProcessFile(searchPath, manifestItem, ref strECID))
return false;
}
else
{
string fileOnly = manifestItem.Path.Substring(manifestItem.Path.LastIndexOf("/") + 1);
searchPath = subdir + "\\" + fileOnly;
if (System.IO.File.Exists(searchPath))
{
Console.WriteLine(" - [Alternate Path] " + fileOnly);
if (!ProcessFile(searchPath, manifestItem, ref strECID))
return false;
}
}
}
return true;
}
static bool ProcessFile(string filename, BuildManifestItem manifestItem, ref string strECID)
{
manifestItem.Found = true;
System.IO.BinaryReader binaryReader = new System.IO.BinaryReader(System.IO.File.OpenRead(filename));
binaryReader.BaseStream.Seek(-2125, System.IO.SeekOrigin.End);
byte[] magic = binaryReader.ReadBytes(4);
StringBuilder sb = new StringBuilder(100);
foreach (byte b in magic)
{
sb.Append((char)b);
}
string magicstr = sb.ToString();
if (magicstr != "DICE")
{
Console.WriteLine(" - ERROR: Magic string not found! (DICE)");
return false;
}
// chew bytes to get to the ecid
binaryReader.ReadBytes(8);
// get the ECID
byte[] ecid = binaryReader.ReadBytes(8);
StringBuilder sbECID = new StringBuilder(20);
for (int idxECID = ecid.Length - 1; idxECID >= 0; idxECID--)
{
sbECID.Append(ecid[idxECID].ToString("x2"));
}
string strThisECID = sbECID.ToString();
if (strECID != null && strThisECID != strECID)
{
Console.WriteLine(" - ERROR: ECID Mismatch (Had: " + strECID + " Found: " + strThisECID + ")");
return false;
}
else if (strECID == null)
{
strECID = strThisECID;
Console.WriteLine("Detected ECID: " + strECID);
}
binaryReader.BaseStream.Seek(-2125, System.IO.SeekOrigin.End);
byte[] signedBytes = binaryReader.ReadBytes(2125);
string signedBytesEncoded = System.Convert.ToBase64String(signedBytes);
StringBuilder formattedBlobDataBuilder = new StringBuilder(3000);
for (int idxChar = 0, colCount = 0; idxChar < signedBytesEncoded.Length; idxChar++, colCount++)
{
formattedBlobDataBuilder.Append(signedBytesEncoded[idxChar]);
if (colCount + 1 == 60)
{
formattedBlobDataBuilder.Append("\n\t\t");
colCount = -1;
}
}
string formattedBlobData = formattedBlobDataBuilder.ToString();
manifestItem.BlobData = formattedBlobData;
return true;
}
}
public class BuildManifestItem
{
string _key;
public string Key
{
get { return _key; }
set { _key = value; }
}
string _path;
public string Path
{
get { return _path; }
set { _path = value; }
}
string _partialDigest;
public string PartialDigest
{
get { return _partialDigest; }
set { _partialDigest = value; }
}
string _blobData;
public string BlobData
{
get { return _blobData; }
set { _blobData = value; }
}
bool _found;
public bool Found
{
get { return _found; }
set { _found = value; }
}
}
public class BuildManifestReader
{
private Dictionary<string, BuildManifestItem> _manifestItems;
public Dictionary<string, BuildManifestItem> ManifestItems
{
get { return _manifestItems; }
set { _manifestItems = value; }
}
public BuildManifestReader(string manifestFilename)
{
_manifestItems = new Dictionary<string, BuildManifestItem>();
System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(Util.ReadEmbeddedResource(manifestFilename));
string elementName = null;
bool foundManifest = false;
BuildManifestItem manifestItem = null;
while (xmlReader.Read())
{
if (xmlReader.NodeType == System.Xml.XmlNodeType.Element)
{
elementName = xmlReader.Name;
}
else if (elementName == "key" && xmlReader.Depth == 5 && xmlReader.NodeType == System.Xml.XmlNodeType.Text)
{
if (xmlReader.Value == "ApBoardID")
{
foundManifest = false;
}
else if (xmlReader.Value == "Manifest")
{
foundManifest = true;
}
}
else if (elementName == "key" && xmlReader.Depth == 6 && xmlReader.NodeType == System.Xml.XmlNodeType.Text)
{
if (foundManifest)
{
manifestItem = new BuildManifestItem();
manifestItem.Key = xmlReader.Value;
}
}
else if (elementName == "key" && xmlReader.NodeType == System.Xml.XmlNodeType.Text && xmlReader.Value == "Path")
{
string path = GetPath(xmlReader);
manifestItem.Path = path;
}
else if (elementName == "key" && xmlReader.NodeType == System.Xml.XmlNodeType.Text && xmlReader.Value == "PartialDigest")
{
string digest = GetPartialDigest(xmlReader);
digest = digest.Replace("\n", "");
digest = digest.Replace("\t", "");
manifestItem.PartialDigest = digest;
if (!_manifestItems.ContainsKey(manifestItem.Key + "-" + manifestItem.Path))
{
_manifestItems.Add(manifestItem.Key + "-" + manifestItem.Path, manifestItem);
}
manifestItem = null;
}
}
}
string GetPath(System.Xml.XmlReader xmlReader)
{
string elementName = null;
while (xmlReader.Read())
{
if (xmlReader.NodeType != System.Xml.XmlNodeType.Element && xmlReader.NodeType != System.Xml.XmlNodeType.Text)
continue;
if (xmlReader.NodeType == System.Xml.XmlNodeType.Element)
{
elementName = xmlReader.Name;
}
else if (elementName == "string" && xmlReader.NodeType == System.Xml.XmlNodeType.Text)
{
return xmlReader.Value;
}
else
{
return null;
}
}
return null;
}
string GetPartialDigest(System.Xml.XmlReader xmlReader)
{
string elementName = null;
while (xmlReader.Read())
{
if (xmlReader.NodeType != System.Xml.XmlNodeType.Element && xmlReader.NodeType != System.Xml.XmlNodeType.Text)
continue;
if (xmlReader.NodeType == System.Xml.XmlNodeType.Element)
{
elementName = xmlReader.Name;
}
else if (elementName == "data" && xmlReader.NodeType == System.Xml.XmlNodeType.Text)
{
return xmlReader.Value;
}
else
{
return null;
}
}
return null;
}
}
class Util
{
public static System.IO.Stream ReadEmbeddedResource(string resourceName)
{
System.Reflection.Assembly curAssembly = System.Reflection.Assembly.GetExecutingAssembly();
string [] resources = curAssembly.GetManifestResourceNames();
foreach (string resource in resources)
{
if (resource.EndsWith(resourceName))
{
return curAssembly.GetManifestResourceStream(resource);
}
}
return null;
}
}
}
Diagnostic: For security reasons DTD is prohibited in this XML document. To enab
le DTD processing set the ProhibitDtd property on XmlReaderSettings to false and
pass the settings into XmlReader.Create method. at System.Xml.XmlTextReaderI
mpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.ThrowWithoutLineInfo(String res, String arg)
at System.Xml.XmlTextReaderImpl.ParseDoctypeDecl()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlTextReaderImpl.Read()
at SHSH_Tool.BuildManifestReader..ctor(String manifestFilename) in C:\Users\A
dministrator\Desktop\shsh\Program.cs:line 323
at SHSH_Tool.Program.Main(String[] args) in C:\Users\Administrator\Desktop\sh
sh\Program.cs:line 87
Complete.
I don't think you gave us the actual XML document that you are reading. It probably has a "DOCTYPE" at the top which specifies a .DTD file.
Either edit the document to not have the DOCTYPE, or programatically ignore the DOCTYPE. Here is how you can do that: Ignore DOCTYPE .dtd, but .dtd file must still exist

Categories