使用ph-schematron时解决相对路径问题

6
我正在使用ph-schematron,这是一个Java库,通过ISO Schematron验证XML文档:
该库提供两种XML文档验证方式:
- 通过XSLT进行验证 - 通过纯Schematron进行验证
我希望使用第二种方式,但我的Schematron文件包含XSLT函数,因此我们必须使用使用XSLT进行验证而不是纯Schematron。
我有一个验证方法,它有两个输入参数:
- schematron文件的XSLT表示 - 要验证的XML文档
现在我的XSLT文件包含以下行:
<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" />

doc函数查找的是项目主目录中名为“include”的文件夹,而不是相对于XSLT文档的文件夹(后者更合乎逻辑)。

现在我遇到了以下异常:

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)

如何强制doc函数查看与XSLT文件同一目录中的include文件夹,而不是在Java项目根目录中查找?

2个回答

5
我找到了一个解决方案:
我定义了自己的 URIResolver 实现,这将在 ph-schematron 内部用作 XSLT 处理器:
class ClasspathResourceURIResolver implements URIResolver {

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

然后将此URI解析器设置为SchematronResourceXSLT:

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

下一步,我们可以检查schematron文件是否有效,并检查XML文档的有效性:
 if (!schematronResourceXslt.isValidSchematron())
        throw new IllegalArgumentException ("Invalid Schematron!");
 final StreamSource xmlSource = new StreamSource(xmlFile);
 final EValidity schematronValidity = schematronResourceXslt.getSchematronValidity(xmlSource);

现在他成功地在XSLT文件中检索到了相对路径。

希望这能对其他人有所帮助。


2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接