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


Reply via email to