I am trying to validate XML using an online XSD. Here is my current code for my controller:
using System;
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using Microsoft.AspNetCore.Mvc;
namespace EINV.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class XmlController : Controller
{
[HttpPost]
public IActionResult ValidateXml2(IFormFile xmlFile, string xsdUrl)
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.XmlResolver = new XmlXsdResolver(); // Need this for resolving include and import
settings.ValidationType = ValidationType.Schema; // This might not be needed, I am using same settings to validate the input xml
//settings.DtdProcessing = DtdProcessing.Parse; // I have an include that is dtd. maybe I should prohibit dtd after I compile the xsd files.
settings.Schemas.Add(null, xsdUrl); // https://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/UBL-Invoice-2.1.xsd
settings.Schemas.Compile();
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create(xmlFile.OpenReadStream(), settings, "https://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/");
XmlDocument document = new XmlDocument();
document.Load(reader);
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
// the following call to Validate succeeds.
document.Validate(eventHandler);
// Load the XML file into an XmlDocument
return Ok();
}
protected class XmlXsdResolver : XmlUrlResolver
{
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
}
private void ValidationEventHandler(object? sender, ValidationEventArgs? e)
{
if (e?.Severity == XmlSeverityType.Error)
{
throw new Exception("XML validation error: " e.Message);
}
}
}
}
I have referenced several other posts in trying to resolve this, such as the following:
Compiling two embedded XSDs: error "Cannot resolve 'schemaLocation' attribute
Validating xml against an xsd that has include and import in c#
But always end up with the same error:
System.Xml.Schema.XmlSchemaValidationException: 'The 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2:UBLExtensions' element is not declared.'
The XML that I am using, which I downloaded into a file and upload through my SWAGGER when calling the controller, is located here: https://docs.oasis-open.org/ubl/os-UBL-2.1/xml/UBL-Invoice-2.1-Example.xml
The XSD that I am using is located here: https://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/UBL-Invoice-2.1.xsd
CodePudding user response:
I think you need to set settings.Schemas.XmlResolver = new XmlUrlResolver();
as well, as the flag settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
before.
That might get you only further as I think some schemas (e.g. for signatures) are imported and not found. So in the end you will need to make sure you have local copies of those schemas and have your resolver use the local copies.