XSD validation: cache invalidation stopped working

Thursday, 26 December 2024 · 5 messages · last reply 30 Dec 2024
Y
ykhabins26 Dec 2024 17:06 #
Hello, My environment has BaseX 11.6 installed. The XQuery is called in c# via REST HTTP call: string REQUESTURL = $"http://{HOST}:{PORT}/rest?run={XQUERY}&$xml={xmlFile}&$xsd={xsdFile}"; XQuery is using XSD validation with caching, along the following: let $result := validate:xsd-report($xml, $xsd, map { 'http://apache.org/xml/features/validation/cta-full-xpath-checking': true(), 'cache': true() }) It seems that the cache invalidation call stopped working ?! It is not picking up the latest XSD. I launch it from the BaseX GUI as follows: validate:xsd-init() Just restart of the HTTP listener picks up the latest/modified XSD. Please advise. Regards, Yitzhak Khabinsky
CG
Christian Grün29 Dec 2024 21:26 #
Hi Yitzhak, A self-contained example would be helpful. Thanks in advance, Christian
Quoted text · PM · 30 lines
On Thu, Dec 26, 2024 at 4:07 PM <ykhabins at bellsouth.net> wrote: > Hello, > > My environment has BaseX 11.6 installed. > > The XQuery is called in c# via REST HTTP call: > string REQUESTURL = > $"http://{HOST}:{PORT}/rest?run={XQUERY}&$xml={xmlFile}&$xsd={xsdFile}"; > > XQuery is using XSD validation with caching, along the following: > let $result := validate:xsd-report($xml, $xsd, map { > 'http://apache.org/xml/features/validation/cta-full-xpath-checking': > true(), > 'cache': true() }) > > It seems that the cache invalidation call stopped working ?! > It is not picking up the latest XSD. > > I launch it from the BaseX GUI as follows: > validate:xsd-init() > > Just restart of the HTTP listener picks up the latest/modified XSD. > > Please advise. > > Regards, > Yitzhak Khabinsky > > >
Y
ykhabins30 Dec 2024 04:53 #
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
CG
Christian Grün30 Dec 2024 09:46 #
Quoted text · ykhabins · 3 lines
> Execute in BaseX GUI: > validate:xsd-init() > Re-run c# REST HTTP CALL emits incorrect result.
Note that the GUI runs in an independent JVM; it does not influence HTTP calls. If I got you wrong, please strip everything that does not seem to contribute to the erroneous behavior; see [1] for more information. Best, Christian [1] https://sscce.org/
Y
ykhabins30 Dec 2024 16:55 #
Hello,
Quoted text · Christian Grün · 1 line
>> Note that the GUI runs in an independent JVM; it does not influence HTTP
calls. The explanation was very helpful. I ended up with a CURL command to invalidate XSD that is cached behind HTTP listener calls (different JVM). curl -i -u <username>:<password> -X POST -H "Content-Type: application/xml" -d "<query xmlns='http://basex.org/rest'><text>validate:xsd-init()</text></query>" "http://<host>:8080/rest" It emits the following: HTTP/1.1 200 OK Date: Mon, 30 Dec 2024 14:44:03 GMT Content-Type: application/xml; charset=UTF-8 Content-Length: 0 Server: Jetty(11.0.24) And everything is working as expected. Thanks a lot. Regards, Yitzhak Khabinsky

⚡Generated with XQuery