Here is a full repro.
Initial setup, four files:
1) XML: e:\Temp\XSD_CACHE\input.xml
2) XSD: e:\Temp\XSD_CACHE\state.xsd
3) XQuery: c:\Program Files (x86)\BaseX\webapp\XSD11_Validation_RECEIPT_2.xq
4) c# file making BaseX REST HTTP call
XML file: e:\Temp\XSD_CACHE\input.xml
======================================
<?xml version="1.0"?>
<root>
<state>FL</state>
<state>TX</state>
</root>
XSD file: e:\Temp\XSD_CACHE\state.xsd
=========================================
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" version="1.0.0">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded"
ref="state"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="state" type="state_type"/>
<xs:simpleType name="state_type">
<xs:restriction base="xs:string">
<xs:length value="2"/>
<xs:enumeration value="FL"/>
<!--<xs:enumeration value="TX"/>-->
</xs:restriction>
</xs:simpleType>
</xs:schema>
XQuery file: XSD11_Validation_RECEIPT_2.xq
==========================================
declare variable $xml as xs:string external;
declare variable $xsd as xs:string external;
try
{
let $timezone := timezone-from-dateTime(current-dateTime())
let $before_datetime :=
adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()),
xs:dayTimeDuration($timezone)) (: current-dateTime() :)
let $result := validate:xsd-report($xml, $xsd, map {
'http://apache.org/xml/features/validation/cta-full-xpath-checking': true(),
'cache': true() })
let $after_datetime :=
adjust-dateTime-to-timezone(convert:integer-to-dateTime(prof:current-ms()),
xs:dayTimeDuration($timezone)) (: current-dateTime() :)
return <root><metadata>
<result>{data($result/status)}</result>
<errors>{count($result/message[@level="Error"])}</errors>
<warnings>{count($result/message[@level="Warning"])}</warnings>
<startTime>{$before_datetime}</startTime>
<endTime>{$after_datetime}</endTime>
<xmlFile>{$xml}</xmlFile>
<xsdFile>{$xsd}</xsdFile>
<xsdProcessor>BaseX {data(db:system()//version)}, Java
{proc:property('java.vendor')} v.{proc:property('java.runtime.version')},
{validate:xsd-processor()} 2.12.2</xsdProcessor>
<xsdVersion>{data(doc($xsd)/*:schema/@version)}</xsdVersion>
</metadata>
<messages>{
$result/message transform with
{ delete node @url }
}</messages>
</root>
}
catch *
{
<error>
<errorCode>{$err:code}</errorCode>
<errorDescription>{$err:description}</errorDescription>
</error>
}
c# REST HTTP call:
==================
void Main()
{
const string HOST = "HostName";
const int PORT = 8080;
const string USERNAME = "username";
const string PASSWORD = "password";
System.Net.ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 |
SecurityProtocolType.Tls;
const string XQUERY = "XSD11_Validation_RECEIPT_2.xq";
string xmlFile = @"e:\Temp\XSD_CACHE\input.xml";
string xsdFile = @"e:\Temp\XSD_CACHE\state.xsd";
string REQUESTURL =
$"http://{HOST}:{PORT}/rest?run={XQUERY}&$xml={xmlFile}&$xsd={xsdFile}";
try
{
using (HttpClientHandler handler = new HttpClientHandler()
{UseDefaultCredentials = true})
// for mdpd proxy
//{UseDefaultCredentials = true, UseProxy = true,
DefaultProxyCredentials = CredentialCache.DefaultNetworkCredentials})
using (HttpClient client = new HttpClient(handler))
{
// Encode username and password pair with a base64
implementation.
String encoded =
Convert.ToBase64String(Encoding.UTF8.GetBytes(USERNAME + ":" + PASSWORD));
client.DefaultRequestHeaders.Add("Authorization",
"Basic " + encoded);
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/xml"));
var response = client.GetAsync(REQUESTURL).Result;
System.Net.Http.HttpContent content =
response.Content;
var contentString =
content.ReadAsStringAsync().Result; // get the actual content string
if (response.StatusCode == HttpStatusCode.OK) //
200 //IsSuccessStatusCode == True
{
XDocument xdoc2 =
XDocument.Parse(contentString);
Console.WriteLine(xdoc2);
string fileRECEIPT =
$@"{Path.Combine(Path.GetDirectoryName(xmlFile),
Path.GetFileNameWithoutExtension(xmlFile))}_RECEIPT_{DateTime.Now.ToString("
yyyy-MM-ddTHH-mm-ss")}.xml";
xdoc2.Save(fileRECEIPT, SaveOptions.None);
}
else
{
string fileErrorResponse =
$@"{Path.Combine(Path.GetDirectoryName(xmlFile),
Path.GetFileNameWithoutExtension(xmlFile))}_ErrorResponse_{DateTime.Now.ToSt
ring("yyyy-MM-ddTHH-mm-ss")}.xml";
File.WriteAllText(fileErrorResponse,
contentString);
}
}
}
catch (Exception ex)
{
ex.Message.Dump();
}
}
In BaseX GUI:
SET BINDINGS xml=e:\Temp\XSD_CACHE\input.xml,xsd=e:\Temp\XSD_CACHE\state.xsd
Start BaseX HTTP listener via launching c:\Program Files
(x86)\BaseX\bin\basexhttp.bat
First execution emits the following correct result in both BaseX GUI as well
as c# REST HTTP:
============================================================================
=================
<root>
<metadata>
<result>invalid</result>
<errors>2</errors>
<warnings>0</warnings>
<startTime>2024-12-29T21:00:55.659-05:00</startTime>
<endTime>2024-12-29T21:00:55.729-05:00</endTime>
<xmlFile>e:\Temp\XSD_CACHE\input.xml</xmlFile>
<xsdFile>e:\Temp\XSD_CACHE\state.xsd</xsdFile>
<xsdProcessor>BaseX 11.6, Java Eclipse Adoptium v.22.0.2+9, Xerces
2.12.2</xsdProcessor>
<xsdVersion>1.0.0</xsdVersion>
</metadata>
<messages>
<message level="Error" line="4" column="19">cvc-enumeration-valid: Value
'TX' is not facet-valid with respect to enumeration '[FL]'. It must be a
value from the enumeration.</message>
<message level="Error" line="4" column="19">cvc-type.3.1.3: The value
'TX' of element 'state' is not valid.</message>
</messages>
</root>
Modified XSD file: xsd=e:\Temp\XSD_CACHE\state.xsd
1) attribute version="1.0.1"
2) uncommented <xs:enumeration value="TX"/> to make XML file valid
==========================================================
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" version="1.0.1">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded"
ref="state"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="state" type="state_type"/>
<xs:simpleType name="state_type">
<xs:restriction base="xs:string">
<xs:length value="2"/>
<xs:enumeration value="FL"/>
<xs:enumeration value="TX"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Execute in BaseX GUI:
validate:xsd-init()
Re-run c# REST HTTP CALL emits incorrect result.
It shows correct xsdVersion: 1.0.1, but result is invalid with the same
error
============================================================================
=
<root>
<metadata>
<result>invalid</result>
<errors>2</errors>
<warnings>0</warnings>
<startTime>2024-12-29T21:20:07.457-05:00</startTime>
<endTime>2024-12-29T21:20:07.459-05:00</endTime>
<xmlFile>e:\Temp\XSD_CACHE\input.xml</xmlFile>
<xsdFile>e:\Temp\XSD_CACHE\state.xsd</xsdFile>
<xsdProcessor>BaseX 11.6, Java Eclipse Adoptium v.22.0.2+9, Xerces
2.12.2</xsdProcessor>
<xsdVersion>1.0.1</xsdVersion>
</metadata>
<messages>
<message level="Error" line="4" column="19">cvc-enumeration-valid: Value
'TX' is not facet-valid with respect to enumeration '[FL]'. It must be a
value from the enumeration.</message>
<message level="Error" line="4" column="19">cvc-type.3.1.3: The value
'TX' of element 'state' is not valid.</message>
</messages>
</root>
Though executing XSD11_Validation_RECEIPT_2.xq directly in the BaseX GUI
emits the correct result:
<root>
<metadata>
<result>valid</result>
<errors>0</errors>
<warnings>0</warnings>
<startTime>2024-12-29T21:23:51.738-05:00</startTime>
<endTime>2024-12-29T21:23:51.739-05:00</endTime>
<xmlFile>e:\Temp\XSD_CACHE\input.xml</xmlFile>
<xsdFile>e:\Temp\XSD_CACHE\state.xsd</xsdFile>
<xsdProcessor>BaseX 11.6, Java Eclipse Adoptium v.22.0.2+9, Xerces
2.12.2</xsdProcessor>
<xsdVersion>1.0.1</xsdVersion>
</metadata>
<messages/>
</root>
Just restart of the BaseX HTTP listener resolves the issue with the BaseX
REST HTTP call.
Regards,
Yitzhak Khabinsky