java - 使用 ph-schematron 时解析相对路径

标签 java xml xslt schematron

我正在使用 ph-schematron,这是一个通过 ISO Schematron 验证 XML 文档的 Java 库:

这个库提供了 2 种 XML 文档验证方式:

  • 通过 XSLT 验证
  • 通过 Pure Schematron 验证

我很想使用第二种类型,但我的 Schematron 文件包含 XSLT 函数,因此我们必须使用 XSLT 而不是纯粹的验证。

我有一个有两个输入参数的验证方法:

  • 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 项目的根目录中?

最佳答案

我找到了一个解决方案:

我定义了我自己的 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));
}    

然后将此 URIResolver 设置为 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 文件中的相对路径。

希望这可以帮助别人

关于java - 使用 ph-schematron 时解析相对路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47226063/

相关文章:

java - 如何使用 Spring Boot for Azure B2C 获取 AccessToken

java - JSF2.0 在托管 bean 之间传递值对象

javascript - 关于 xslt 和 javascript 的查询

xml - Azure 集成帐户( map - XSLT)- 使用逻辑应用将 2 个不同的 XML 合并为单个 xml

XSLT:获取月份缩写

java - 如何在 Android 的 xml 中为字符串资源指定空值?

java - 如何在 Java 中将 int[] 转换为 List<Integer>?

java - 方法 getTagValue() 在 JAVA 中未定义

java - 将微调项目存储在字符串值中

java - Jaxb:带注释的类中的属性固定值