Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving relative paths when using ph-schematron

I'm using ph-schematron, a Java library that validates XML documents via ISO Schematron:

This library provides 2 ways of XML document validation:

  • Validation via XSLT
  • Validation via Pure Schematron

I would love to use the second type, but my Schematron files contain XSLT functions so we MUST use the validation using XSLT and not the pure one.

I have a validation method that has two input paramters:

  • The XSLT representation of the schematron file
  • The XML document to validate

Now my XSLT file contains lines like this:

<xsl:when test="count(hl7:confidentialityCode[concat(@code,@codeSystem)=doc('include/voc-1.3.6.1.4.1.12559.11.10.1.3.1.42.31-DYNAMIC.xml')//valueSet[1]/conceptList/concept/concat(@code,@codeSystem) or @nullFlavor])>=1" />

And the doc function looks for a folder called 'include' in the home directory of my project instead of the folder relative to the XSLT document (which would be more logic).

Now I got exceptions like:

java.io.FileNotFoundException: C:\LocalData\Development\projectname\include\voc-1.3.6.1.4.1.12559.11.10.1.3.1.42.31-DYNAMIC.xml (The system cannot find the path specified)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
at org.apache.xerces.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at net.sf.saxon.event.Sender.sendSAXSource(Sender.java:451)
at net.sf.saxon.event.Sender.send(Sender.java:153)
at net.sf.saxon.functions.DocumentFn.makeDoc(DocumentFn.java:330)
at net.sf.saxon.functions.Doc.call(Doc.java:138)
at net.sf.saxon.functions.Doc.call(Doc.java:24)
at net.sf.saxon.expr.FunctionCall.iterate(FunctionCall.java:546)
at net.sf.saxon.expr.Expression.evaluateItem(Expression.java:773)
at net.sf.saxon.expr.SimpleStepExpression.iterate(SimpleStepExpression.java:108)
at net.sf.saxon.expr.SlashExpression.iterate(SlashExpression.java:868)
at net.sf.saxon.expr.SlashExpression.iterate(SlashExpression.java:868)
at net.sf.saxon.expr.SlashExpression.iterate(SlashExpression.java:868)
at net.sf.saxon.expr.SlashExpression.iterate(SlashExpression.java:868)
at net.sf.saxon.value.MemoClosure.iterate(MemoClosure.java:109)
at net.sf.saxon.expr.VariableReference.iterate(VariableReference.java:482)
at net.sf.saxon.expr.GeneralComparison.effectiveBooleanValue(GeneralComparison.java:621)
at net.sf.saxon.expr.OrExpression.effectiveBooleanValue(OrExpression.java:131)
at net.sf.saxon.expr.FilterIterator$NonNumeric.matches(FilterIterator.java:198)
at net.sf.saxon.expr.FilterIterator.getNextMatchingItem(FilterIterator.java:81)
at net.sf.saxon.expr.FilterIterator.next(FilterIterator.java:64)
at net.sf.saxon.functions.Exists$1.effectiveBooleanValue(Exists.java:67)
at net.sf.saxon.expr.instruct.Choose.choose(Choose.java:865)
at net.sf.saxon.expr.instruct.Choose.processLeavingTail(Choose.java:840)
at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:653)
at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:353)
at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:456)
at net.sf.saxon.trans.TextOnlyCopyRuleSet.process(TextOnlyCopyRuleSet.java:65)
at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:433)
at net.sf.saxon.expr.instruct.ApplyTemplates.apply(ApplyTemplates.java:298)
at net.sf.saxon.expr.instruct.ApplyTemplates.processLeavingTail(ApplyTemplates.java:255)
at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:653)
at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:149)
at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:364)
at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:311)
at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:353)
at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:456)
at net.sf.saxon.Controller.transformDocument(Controller.java:2321)
at net.sf.saxon.Controller.transform(Controller.java:1892)
at net.sf.saxon.s9api.XsltTransformer.transform(XsltTransformer.java:579)
at net.sf.saxon.jaxp.TransformerImpl.transform(TransformerImpl.java:185)
at com.helger.schematron.xslt.AbstractSchematronXSLTBasedResource.applySchematronValidation(AbstractSchematronXSLTBasedResource.java:273)
at com.helger.schematron.xslt.AbstractSchematronXSLTBasedResource.applySchematronValidationToSVRL(AbstractSchematronXSLTBasedResource.java:288)
at com.helger.schematron.xslt.AbstractSchematronXSLTBasedResource.getSchematronValidity(AbstractSchematronXSLTBasedResource.java:197)
at com.helger.schematron.AbstractSchematronResource.getSchematronValidity(AbstractSchematronResource.java:210)
at epsos.ccd.posam.tm.util.NewSchematronValidator.doValidate(NewSchematronValidator.java:47)
at epsos.ccd.posam.tm.util.NewSchematronValidator.validate(NewSchematronValidator.java:39)
at epsos.ccd.posam.tm.util.SchematronValidatorTest.testValidationNew(SchematronValidatorTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

How can I force the doc function to look at the include folder in the same directory as the XSLT file and not in the root of my Java Project?

like image 737
Mathias G. Avatar asked Nov 10 '17 15:11

Mathias G.


1 Answers

I found a solution:

I defined my own implementation of an URIResolver, that will be used as an XSLT processor internally by ph-schematron:

class ClasspathResourceURIResolver implements URIResolver {

    @Override
    public Source resolve(String href, String base) throws TransformerException {
        return new StreamSource(this.getClass().getClassLoader().getResourceAsStream(href));
}    

This URIResolver is then set to the SchematronResourceXSLT:

IReadableResource readableResource = new ReadableResourceInputStream(new FileInputStream(schematronFile));
SchematronResourceXSLT schematronResourceXslt = new SchematronResourceXSLT(readableResource);
schematronResourceXslt.setURIResolver(new ClasspathResourceURIResolver());

Next we can check if the schematron file is valid and check the validity of an XML document:

 if (!schematronResourceXslt.isValidSchematron())
        throw new IllegalArgumentException ("Invalid Schematron!");
 final StreamSource xmlSource = new StreamSource(xmlFile);
 final EValidity schematronValidity = schematronResourceXslt.getSchematronValidity(xmlSource);

And now he manages to retrieve the relative paths in the XSLT file.

Hope this can help someone else

like image 109
Mathias G. Avatar answered Sep 23 '22 11:09

Mathias G.