XmlReaderSettings.Schemas.Add() : The URI prefix is not recognized - c#

I upgraded my old application in .Net 4.5. There are some obsolete methods warnings I was getting so thought to resolve them. One of the obsolete methods is XmlValidatingReader.
Looked up on the internet and found that XmlReaderSettings is a potential alternate of XmlValidatingReader.
// ==old code==
Hashtable _SchemasCache = new Hashtable();
XmlReader xmlReader = new XmlTextReader(xmlStream);
XmlValidatingReader validatingReader = new XmlValidatingReader(xmlReader);
validatingReader.Schemas.Add(root.Namespace, schemaLocation); // both parametres are string. No error
_SchemasCache.Add(schemaLocation, validatingReader.Schemas);
// ==new code==
var schemaLocation = "res://somepath/Messages.xsd";
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(root.Namespace, schemaLocation); // this line gives error
_SchemasCache.Add(schemaLocation, settings.Schemas);
old code doesn't give any error but the new code gives an error of The URI prefix is not recognized. I couldn't find the reason for this behavior of settings.Schemas.Add(), as it is working fine with XmlValidatingReader. Can anyone help with this?
Edit: Here value of schemaLocation is "res://somepath/Messages.xsd". Because schemaLocation has no Http: or https:// or not a local resource, that is why the error is occurring. How can I add schemas with these values using XmlReaderSettings
Edit 2: as this XSD is an embedded resource, I found some code online for this scenario. I made below code changes.
Assembly asm = Assembly.Load("AssemblyNameWhereXSDis");
Uri uri = new Uri(#"res://p.a.t.h/Autorisatie/Messages.xsd");
string resourceName1 = asm.GetName().Name + uri.AbsolutePath.Replace("/", ".");
using (Stream schemaStream = myAssembly.GetManifestResourceStream(resourceName1))
{
using (XmlReader schemaReader = XmlReader.Create(schemaStream)) // this line gives error : value(schemaStream) cannot be null
{
settings.Schemas.Add(root.Namespace, schemaReader);
}
}
here, the value of schemaStream is null. And the value of resourceName1 is assemblyname.folder.Message.xsd.
I have made Message.xsd as Embedded Resource from Visual Studio but still not working.

Source of issue
As you figured yourself - URI has to point to a REAL file somewhere - either a URL (HTTP/HTTPS) or a local file ("C:\...").
So, if you prefer using an Embedded Resource instead, you need to use a fully-specified path in the following form:
"Namespace.FolderName.Filename.Extension"
Example
using System;
using System.Linq;
using System.Reflection;
using System.Xml;
// ...
// get full resourceName from current assembly using Linq
var messagesResourceFullName = Assembly.GetExecutingAssembly()
.GetManifestResourceNames()
.Where(n => n.EndsWith("Messages.xsd"));
using (var schemaStream = asm.GetManifestResourceStream(messagesResourceFullName))
{
if (schemaStream == null) throw new FileNotFoundException();
using (var schemaReader = XmlReader.Create(schemaStream))
{
settings.Schemas.Add(root.Namespace, schemaReader);
}
}
source

Add this line in your code :
using System.Linq;

Related

How to programmatically find the sha of a github file

I am trying to make an interface between my code and my personal gihub repo and my current issue is that I need to be able to automatically make calls to rewrite the data of a github file. However the main article which has helped me write this code, as well as the github OctoKit docs claim I need the file's sha key in order to make any changes to it.
These are all of my imports currently:
using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using System; using System.Collections.Generic; using System.Windows.Forms; using System.IO.Packaging; using System.Net; using System.IO; using Octokit; using System.Text;
I have tried in-depth research through the .Net docs as well as the OctoKit docs and digging through the attributes of every single line. Nothing has yielded any clues as to how to find the sha of a github file. The main article I was following used this line to get the sha, fileDetails.First().sha and 'fileDetails' is created using this line: var fileDetails = gitHubClient.Repository.Content.GetAllContentsByRef(owner, repoName,filePath, branch); however, for Visual Studio 2019, it throws a CS1061 Error claiming this data type cannot have First() applied to it.
My code is below for this specific problem. If you know anything thank you very much for your time. If not thanks for a visit. Again if anyone has any insight to fixing this I am in debt to you truly.
`private void write_new_announcements_to_website(string websiteurl, string newAnnouncements) {
GitHubClient gitHubClient = new GitHubClient(new ProductHeaderValue("jerry-spice.github.io"));
gitHubClient.Credentials = new Credentials("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");
var sb = new StringBuilder("");
sb.AppendLine(newAnnouncements);
var (owner, repoName, filePath, branch) = ("Jerry-Spice", "jerry-spice.github.io",
websiteurl, "main");
/*gitHubClient.Repository.Content.CreateFile(
owner, repoName, filePath,
new CreateFileRequest($"Updated info for {filePath}", sb.ToString(), branch));*/
var fileDetails = gitHubClient.Repository.Content.GetAllContentsByRef(owner, repoName,filePath, branch);
//Console.WriteLine(fileDetails)
var updateResult = gitHubClient.Repository.Content.UpdateFile(owner, repoName, filePath,
new UpdateFileRequest("My updated file", sb.ToString(), fileDetails.First().sha));
}
`
The problem is GetAllContentsByRef returns as Task. You'll need to await the call to get the data. Also, the SHA property is proper case. See the following changes.
GitHubClient gitHubClient = new GitHubClient(new ProductHeaderValue("jerry-spice.github.io"));
gitHubClient.Credentials = new Credentials("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");
var sb = new StringBuilder("");
sb.AppendLine(newAnnouncements);
var (owner, repoName, filePath, branch) = ("Jerry-Spice", "jerry-spice.github.io",
websiteurl, "main");
/*gitHubClient.Repository.Content.CreateFile(
owner, repoName, filePath,
new CreateFileRequest($"Updated info for {filePath}", sb.ToString(), branch));*/
var fileDetails = await gitHubClient.Repository.Content.GetAllContentsByRef(owner, repoName,filePath, branch);
//Console.WriteLine(fileDetails)
var updateResult = gitHubClient.Repository.Content.UpdateFile(owner, repoName, filePath,
new UpdateFileRequest("My updated file", sb.ToString(), fileDetails.First().Sha));

Fully Qualified Namespace Metadata Error with Roslyn

I am trying to make a code analyzer which checks for fully qualified using statements. This link has been incredibly helpful, and the basis for my solution (How can I get the fully qualified namespace from a using directive in Roslyn?) but I am running into a problem when I try to access the location of the symbol for the using directive. My code looks like this:
private static void AnalyzeModel(SemanticModelAnalysisContext semanticModelAnalysisContext)
{
var semanticModel = semanticModelAnalysisContext.SemanticModel;
var root = semanticModel.SyntaxTree.GetRoot();
// compare each using statement's name with its fully qualified name
foreach (var usingDirective in root.DescendantNodes().OfType<UsingDirectiveSyntax>())
{
var symbol = semanticModel.GetSymbolInfo(usingDirective.Name).Symbol;
var fullyQualifiedName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
if (fullyQualifiedName.Contains(GlobalTag))
{
fullyQualifiedName = fullyQualifiedName.Substring(GlobalTag.Length);
}
if (usingDirective.Name.ToString() != fullyQualifiedName)
{
// for each name that is not fully qualified, produce a diagnostic.
var diagnostic = Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name);
semanticModelAnalysisContext.ReportDiagnostic(diagnostic);
}
}
}
The problem is the symbol.Locations[0] only contains items in metadata, not items in source. This leads to the following error:
Assert.IsTrue failed. Test base does not currently handle diagnostics in metadata locations.
My source in my unit tests looks like this:
private const string incorrectSourceCode = #"
namespace System
{
using IO;
using Threading;
}";
Why are there no items in symbol.Locations that are in source? Is there another place I can get this location? I've tried using symbol.ContainingSymbol.Locations[0] or symbol.ContainingNamespace.Locations[0], but those are not referring to the using specific using that I am interested in. I've been pulling out my hair over this for hours, and some clarity would be very greatly appreciated.
Thanks in advance!
Symbol contains MetadateLocation, so if you want to see SourceLocation just retrieve it from the appropriate SyntaxNode:
var diagnostic = Diagnostic.Create(Rule, usingDirective.Name.GetLocation(), symbol.Name)
instead of
var diagnostic = Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name)

XmlReader testing of string returned for newline

I am writing a C# class to use for generating email lists to use when a process either succeeds or fails. In running through XmlReader examples from the web, I found that validating the Read() is tougher than it looks.
I can use string.IsNullOrEmpty(x) to test for a null value or and empty node, but it will still blow by that test showing a "\n " in the tooltip for x. Testing for "\n ", '\n ', '\n'. "\n" or char(13) all fail. If I use x.Contains((char)13), it always find it and goes into the code trying to build the email address list. So far, it either always fails or always succeeds.
I found some old posts on stackoverflow where it seemed like the question was the same, but my results don't match with the answers. My environment is Windows 8.1 running Visual Studio 2013 with .Net Framework 4.51. The example from the web I was trying to make work before using the solution in my class is at Microsoft.com
My conversion is below:
using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using System.Collections.Generic;
namespace XMLDemo
{
public class project
{
public static void Main()
{
string uri = #"C:\\events\items.xml";
string process_state = "Item";
string emails = StreamEmailAddress(uri, process_state);
}
private static string StreamEmailAddress(string uri, string process_state)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
XmlReader reader = XmlReader.Create(uri, settings);
string returnValue = "";
reader.MoveToContent();
while (reader.Read())
{
string x = reader.Value;
if ((string.IsNullOrEmpty(x) == false) && (x.Contains((char)13)))
{
returnValue = returnValue + x + "; ";
}
}
Console.WriteLine("Made it to the end: " + returnValue);
return returnValue;
}
}
}
You should use string.IsNullOrWhiteSpace
SOLVED: After futzing with it all day, I looked at it with slightly fresher eyes after posting and saw the blatant error. I was using the incorrect function and trying to resolve line feeds by myself. By replacing IsNullOrEmpty(x) with IsNullOrWhiteSpace(x), I got the string of data as expected. Doing the code with email addresses will be easy now.

System.XML on XAMARIN forms project

I am trying to use XmlDocument class **
and **XmlDocument .Load(..) function
on the Portable Project of XAMARIN.Forms Portable solution with visual studio community.
The compiler says that "The type or namespace name 'XmlDocument' could not be found (are you missing a using directive or an assembly reference?"
If i go in References it don't allow me to add the System.XML namespace (there is no) and if i browse file and go to system.xml.dll it says me that the file could not be added because this component is already automatically referenced by build system.
what i can to do to use the class??
NOTE:
in .Droid and .IOS project there is a referenc to System.xml and in those projects I can use XmlDocument class.
PCL doesn't support XmlDocument. You can use System.Xml.Linq.XDocument instead.
The XmlDocument class is not available for use in a PCL library, as you can see on its documentation page under Version Information. (Compare to the Version Information section of the XmlDictionary class - notice how this class has Portable Class Library available while XmlDocument does not.)
If you want to use an XmlDocument, you'll have to create a dependency service and implement it separately under both Android and iOS versions.
I had no trouble adding XML to my project:
using System.Xml;
using System.Xml.Serialization;
public string ToXML(Object oObject)
{
XmlDocument xmlDoc = new XmlDocument();
XmlSerializer xmlSerializer = new XmlSerializer(oObject.GetType());
using (MemoryStream xmlStream = new MemoryStream())
{
xmlSerializer.Serialize(xmlStream, oObject);
xmlStream.Position = 0;
xmlDoc.Load(xmlStream);
return xmlDoc.InnerXml;
}
}
After that the XML string can be shared:
public MvxCommand ShareWaypoints => new MvxCommand(ShareWaypointsAsync);
public async void ShareWaypointsAsync()
{
try
{
string strXML = "";
foreach (var wp in waypoints)
{
strXML += ToXML(wp);
}
if (strXML != "")
await Share.RequestAsync(new ShareTextRequest
{
Text = strXML,
Title = "Share Text"
});
}
catch (Exception ex)
{
await _userDialogs.AlertAsync(ex.Message);
}
}

Dealing with xsd:include XSDs as an embedded resource in Visual Studio

I have a set of XSDs that validate against XMLSPY and against Java code. I need to bring this set of XSDs as an embedded resource in Visual Studio 2012 .net. Unfortunately I am getting an error that a global element has already been declared when trying to resolve them with a custom XmlResolver to deal with the xsd:include. Error is strange because the element is declared only once.
Visual Studio Solution
|----------- Visual Studio Project
|----------- Schemas (Embedded Resource)
|----------- Directory A
|------------ set of XSDs that are referenced by XSDs in Directory B and to a globaltype definition file located in this directory
|----------- Directory B
|------------- set of XSDs that reference each other and those in Directory A, the XSD call from the main is located here
Validating Util Class
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
namespace ABC.XYZ.Utils
{
public static class XmlUtil
{
private static bool isValid;
public static bool ValidateXml(string targetNamespace, string schemaUri, string xml)
{
isValid = true;
var schemaReaderSettings = new XmlReaderSettings() { ValidationType = ValidationType.Schema };
schemaReaderSettings.ValidationEventHandler += MyValidationHandler;
schemaReaderSettings.Schemas.XmlResolver = new XmlResourceResolver();
var schemaReader = XmlReader.Create(GetSchemaStream(schemaUri), schemaReaderSettings);
schemaReaderSettings.Schemas.Add(targetNamespace, schemaReader);
var x = XElement.Parse(xml);
var sr = new System.IO.StringReader(x.ToString());
XmlReader validatingReader = XmlReader.Create(sr, schemaReaderSettings);
while (validatingReader.Read())
{
}
validatingReader.Close();
return isValid;
}
private static void MyValidationHandler(object sender, ValidationEventArgs args)
{
Console.WriteLine("***Validation error");
Console.WriteLine("\tSeverity:{0}", args.Severity);
Console.WriteLine("\tMessage:{0}", args.Message);
isValid = false;
}
private static Stream GetSchemaStream(string relativeFileName)
{
var resourceFileName =
Assembly.GetExecutingAssembly()
.GetManifestResourceNames()
.FirstOrDefault(p => p.EndsWith(relativeFileName));
return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceFileName);
}
}
}
Custom XmlResolver
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace ABC.XYZ.Utils
{
public class XmlResourceResolver : XmlResolver
{
public const string AssemblyDefaultNamespace = "ABC.XYZ";
public const string SchemasNamespace = "Schemas";
public override Uri ResolveUri(Uri baseUri, string relativeUri)
{
var result = new UriBuilder("res://", AssemblyDefaultNamespace, -1, SchemasNamespace.Replace(".", "/"));
result.Path += "/" + relativeUri.Replace("../", "/").TrimStart('/');
return result.Uri;
}
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
if (absoluteUri.Scheme != "res") return null;
Debug.WriteLine("Loading resource based on location {0}", absoluteUri);
var assembly = Assembly.GetExecutingAssembly();
var name = String.Format(CultureInfo.InvariantCulture, "{0}{1}",
absoluteUri.Host,
absoluteUri.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped).Replace("/", "."));
// try for an exact match based on schemaLocation hint path
var resourceName = (from x in assembly.GetManifestResourceNames()
where name.Equals(x, StringComparison.OrdinalIgnoreCase)
select x).FirstOrDefault();
// if not match based on filename alone
if (resourceName == null)
{
var schemaDocumentName = Path.GetFileName(absoluteUri.AbsolutePath);
Debug.WriteLine("Unable to locate exact match, looking for match based on filename {0}", schemaDocumentName);
resourceName = (from x in assembly.GetManifestResourceNames()
where x.Contains(SchemasNamespace) &&
x.EndsWith("." + schemaDocumentName, StringComparison.OrdinalIgnoreCase)
select x).FirstOrDefault();
}
Debug.WriteLine("Loading resource {0}", resourceName);
var stream = assembly.GetManifestResourceStream(resourceName);
return stream;
}
}
}
Any insights into this problem with be greatly appreciated.
XSD 1.0 encourages but does not require validators to detect multiple inclusions (or imports) of the same schema document and include them only once.
The result is that including the same schema document more than once from multiple other schema documents is the simplest way to create interoperability nightmares with XSD. (Not the only way, just the simplest way.) If you own the schema documents, segregate all inclusions and all schema-location information on imports into a driver file and delete all includes and all schema-location hints on imports from the 'normal' schema documents.
The problem is that when you're doing it with XMLSpy, the XSDs are files in the file system; what's happening then, for each file there's a base URI, and therefore resolvers will use that information to ensure that once an XSD is loaded, the same one is not loaded again, based on URI compare.
Now, the way you're doing it by loading as a stream from an assembly, all that information is gone (your stream doesn't have a base URI). Your resolver will keep loading the same XSD over and over again, from different places, thus creating this clash.
All the XSD processors I know, do not employ any other means to filter multiple inclusions of the same XSD content, but base source URI.
In .NET, the easiest way might be (again, depending on how complex your graph is) to try the solution in this post; the whole idea is to provide a base URI, which should give the info required to avoid multiple inclusions.
Another alternative might be to make sure in your custom resolver that for any given URI you're resolving, you only return once a stream (return null in all other cases). This is guaranteed to work as long as you're not using xsd:redefine composition (in which case the solution is to make a topological sort of the schema file graph and ensure all xsd:redefines are loaded first).
To #CMSperbergMcQueen point, an approach that is guaranteed to work is to refactor ALL the XSDs such that there's only one XSD embedded resource per namespace; each XSD would have all imports removed (technique called "dangling"). Add those XSDs to an XML Schema set as independent XSDs and compile. Unless you run into a .NET bug, the result should be a compiled XmlSchemaSet.

Categories