Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 修复XPath表达式中的绝对路径,以便它们在另一个文档的上下文中工作_Java_Xml_Regex_Xslt_Xpath - Fatal编程技术网

Java 修复XPath表达式中的绝对路径,以便它们在另一个文档的上下文中工作

Java 修复XPath表达式中的绝对路径,以便它们在另一个文档的上下文中工作,java,xml,regex,xslt,xpath,Java,Xml,Regex,Xslt,Xpath,我想从XPath表达式中提取对文档根的所有引用,并在它们之后插入一个自定义根 我正在实现基于某种模式语言创建的XML实例文档的一小部分验证(或者说修复一个bug)。这种语言提供了指定自包含的XML块的方法。每个这样的块都在单独的文件中定义,并指定XML元素层次结构。每个这样的层次结构都有一个或多个属于同一文档根的根元素,就像任何XML文档的不可见文档根一样 但是,这些文件不知道这样一个事实,即它们指定的只是更大系统的一部分。这个更大的系统实际上是另一个XML文档(具有另一个文档根),具有单个顶级

我想从XPath表达式中提取对文档根的所有引用,并在它们之后插入一个自定义根

我正在实现基于某种模式语言创建的XML实例文档的一小部分验证(或者说修复一个bug)。这种语言提供了指定自包含的XML块的方法。每个这样的块都在单独的文件中定义,并指定XML元素层次结构。每个这样的层次结构都有一个或多个属于同一文档根的根元素,就像任何XML文档的不可见文档根一样

但是,这些文件不知道这样一个事实,即它们指定的只是更大系统的一部分。这个更大的系统实际上是另一个XML文档(具有另一个文档根),具有单个顶级XML元素,其中包含由任意数量的模式语言文件定义的所有根元素

XML层次结构中的任何节点都可能受到XPath表达式的约束,为了在验证期间将元素视为有效元素,XPath表达式的计算结果必须为true。这就是我问题的根源。这些XPath表达式可能包含绝对位置路径,它引用单个XML块的文档根,而不是系统的文档根。考虑下面的XML实例:


基础
人
约翰·史密斯
有效条目
基础
动物
狗
无效条目
人
基础
{system:uri}data
表示系统,
{root-one:uri}root-one
{root-two:uri}root-two
是两个XML块,每个XML块都在自己的模式语言文件中定义。假设每个
root one/items/item
实例必须满足模式语言文件中定义的以下XPath条件(不要介意
current()
,它的工作原理与XSLT中的相同,指的是
item
实例之一):

实际上应该是

context: /data/root-one/items/item
assert: group=/data/root-one/item-classes/item-class[class=current()/class]/group
如何在任何XPath表达式中获取对文档根(/)的所有引用,并将它们注入正确的根?我无法控制这些表达式是如何形成的,因此它们可以有任何形状和大小,只要它们满足XPath 1.0语法,但我必须让它们正确计算

我目前正在考虑用java编写某种标记器来处理这个问题,但如果有更简单的解决方案,我宁愿不去讨论它。表达式是在系统文档上下文中的Schematron XSLT转换期间进行计算的,因此,如果我能够以某种方式使用XSLT实现路径修复,那就太完美了。不过,我愿意接受任何可以引导我找到解决方案的建议

Edit01

这就是一个包含XPath表达式的示例文件的样子(我想不起来)。我希望转换
@test
属性的内容。
@context
属性的值很容易更改,因为它总是具有类似的结构


项的组必须与预定义的类组之一匹配。
请注意,
@test
属性的值可以是任何有效的XPath 1.0表达式。我想使用一个通用解决方案,它可以找到表达式中任何位置定义的任何文档根(“/”),并将其注入自定义根元素。实际文件可能包含任意数量的
iso:pattern
元素、
iso:rule
元素等

Edit02

对于上面的示例,需要的结果是以下
iso:assert
元素:

项的组必须与预定义的类组之一匹配。
Edit03

作为对如何确定/r1:root one/前面必须加“/tl:data”的响应?你能描述一下规则吗迪米特里·诺瓦切夫

/tl:data
表示文档的根元素,该元素是通过将多个其他XML文档合并到一个文档中创建的。中那些文档的内容作为子元素附加到此根元素
r1:root one
成为此类子级之一。XPath约束是模式定义的一部分,它描述了
r1:root one
的元素结构是什么样子,其设计仅适用于此子XML文档的上下文。当子XML文档被附加到“父”文档时,如果表达式中存在绝对路径,则它们将失去意义。因此,如果表达式包含
/r1:root one
,则在新文档中没有任何意义(其中没有
root one
根元素,
tl:data
是唯一的根)。我希望找到所有这样的情况(
/r1:root one/
),并将它们转换为
/tl:data/r1:root one/
),以便表达式在新文档的上下文中工作

很难指定确切的规则。每次出现在路径开头的“
/
”(因此引用子XML文档的文档根)都应替换为“
/tl:data/
”,因此它现在引用新创建文档的文档根

Edit04

如上文所述,解决方案应该适用于任何可以想象的XPath表达式。其他示例(r1名称空间中虚构的元素是虚构的-这在我脑海中听起来更好):


应该成为

<iso:assert test="r1:group=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group and r1:imaginary-element1=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:imaginary-element1" />
<iso:assert test="r1:group=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=/tl:data/r1:root-one/r1:imaginary-constants/r1:imaginary-constant]/r1:group" />

Edit05

我现在可以选择切换到XSLT2.0处理器。因此,我将接受XSLT2.0解决方案

<iso:assert test="r1:group=/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group and r1:imaginary-element1=/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:imaginary-element1" />
<iso:assert test="r1:group=/r1:root-one/r1:item-classes/r1:item-class[r1:class=/r1:root-one/r1:imaginary-constants/r1:imaginary-constant]/r1:group" />
<iso:assert test="r1:group=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group and r1:imaginary-element1=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:imaginary-element1" />
<iso:assert test="r1:group=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=/tl:data/r1:root-one/r1:imaginary-constants/r1:imaginary-constant]/r1:group" />
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:iso="http://purl.oclc.org/dsdl/schematron"
 xmlns:def="http://purl.oclc.org/dsdl/schematron">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="iso:assert/@test">
  <xsl:attribute name="test">
    <xsl:value-of select=
    "concat(substring-before(.,'/'),'/t1:data/', substring-after(.,'/'))"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>
<iso:schema    xmlns="http://purl.oclc.org/dsdl/schematron"
           xmlns:iso="http://purl.oclc.org/dsdl/schematron"
           xmlns:sch="http://www.ascc.net/xml/schematron"
           xmlns:tl="toplevel:uri"
           xmlns:r1="root-one:uri"
           xmlns:r2="root-two:uri">

  <iso:ns prefix="tl" uri="toplevel:uri" />
  <iso:ns prefix="r1" uri="root-one:uri" />
  <iso:ns prefix="r2" uri="root-two:uri" />

  <iso:pattern>
    <iso:rule context="/r1:root-one/r1:items/r1:item">
      <iso:assert test="r1:group=/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group">The group of an item must match one of the predefined class groups.</iso:assert>
    </iso:rule>
  </iso:pattern>
</iso:schema>
<iso:schema xmlns:iso="http://purl.oclc.org/dsdl/schematron"
 xmlns="http://purl.oclc.org/dsdl/schematron"
 xmlns:sch="http://www.ascc.net/xml/schematron"
 xmlns:tl="toplevel:uri" xmlns:r1="root-one:uri"
 xmlns:r2="root-two:uri">
   <iso:ns prefix="tl" uri="toplevel:uri"/>
   <iso:ns prefix="r1" uri="root-one:uri"/>
   <iso:ns prefix="r2" uri="root-two:uri"/>
   <iso:pattern>
      <iso:rule context="/r1:root-one/r1:items/r1:item">
         <iso:assert test="r1:group=/t1:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group">The group of an item must match one of the predefined class groups.</iso:assert>
      </iso:rule>
   </iso:pattern>
</iso:schema>
<iso:schema xmlns="http://purl.oclc.org/dsdl/schematron"
            xmlns:iso="http://purl.oclc.org/dsdl/schematron"
            xmlns:sch="http://www.ascc.net/xml/schematron"
            xmlns:tl="toplevel:uri"
            xmlns:r1="root-one:uri"
            xmlns:r2="root-two:uri">
   <iso:ns prefix="tl" uri="toplevel:uri"/>
   <iso:ns prefix="r1" uri="root-one:uri"/>
   <iso:ns prefix="r2" uri="root-two:uri"/>
   <iso:pattern>
      <iso:rule context="/r1:root-one/r1:items/r1:item">
         <iso:assert test="r1:group=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group"><!--r1:group=/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group--></iso:assert>
         <iso:assert test="r1:group=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group and r1:imaginary-element1=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:imaginary-element1"><!--r1:group=/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:group and r1:imaginary-element1=/r1:root-one/r1:item-classes/r1:item-class[r1:class=current()/r1:class]/r1:imaginary-element1--></iso:assert>
         <iso:assert test="r1:group=/tl:data/r1:root-one/r1:item-classes/r1:item-class[r1:class=/tl:data/r1:root-one/r1:imaginary-constants/r1:imaginary-constant]/r1:group"><!--r1:group=/r1:root-one/r1:item-classes/r1:item-class[r1:class=/r1:root-one/r1:imaginary-constants/r1:imaginary-constant]/r1:group--></iso:assert>
         <iso:assert test="../type[. * /tl:data/root-one/imaginary-constants/imaginary-constant1 &gt; 10]"><!--../type[. * /root-one/imaginary-constants/imaginary-constant1 > 10]--></iso:assert>
         <iso:assert test="../type[. mod /tl:data/root-one/imaginary-constants/imaginary-constant1 = 1]"><!--../type[. mod /root-one/imaginary-constants/imaginary-constant1 = 1]--></iso:assert>
         <iso:assert test="/tl:data/root-one/imaginary-constants/imaginary-constant1"><!--   /root-one/imaginary-constants/imaginary-constant1--></iso:assert>
         <iso:assert test="../type[. mod /tl:data/root-one/imaginary-constants/imaginary-constant1 = 1]"><!--../type[. mod /root-one/imaginary-constants/imaginary-constant1 = 1]--></iso:assert>
         <iso:assert test="../group= /tl:data/root-one/item-classes/item-class[name=current()/name]/group and ../class=/tl:data/root-one/item-classes/item-class[name=current()/name]/class"><!--../group= /root-one/item-classes/item-class[name=current()/name]/group and ../class=/root-one/item-classes/item-class[name=current()/name]/class--></iso:assert>
         <iso:assert test="../type[. = /tl:data/root-one/imaginary-constants/imaginary-constant1]"><!--../type[. = /root-one/imaginary-constants/imaginary-constant1]--></iso:assert>
         <iso:assert test="../type[.*/tl:data/root-one/imaginary-constants/imaginary-constant1 = 1]"><!--../type[.*/root-one/imaginary-constants/imaginary-constant1 = 1]--></iso:assert>
         <iso:assert test="../type[/tl:data/root-one/imaginary-constants/imaginary-constant1 mod ../../*/type]"><!--../type[/root-one/imaginary-constants/imaginary-constant1 mod ../../*/type]--></iso:assert>
         <iso:assert test="../type[/tl:data/root-one/imaginary-constants/imaginary-constant1 mod ../multiminus---/type &gt; 1]"><!--../type[/root-one/imaginary-constants/imaginary-constant1 mod ../multiminus- - -/type > 1]--></iso:assert>
         <iso:assert test="../type[../multiminus---*/tl:data/root-one/imaginary-constants/imaginary-constant1 &gt; 1]"><!--../type[../multiminus- - -*/root-one/imaginary-constants/imaginary-constant1 > 1]--></iso:assert>
         <iso:assert test="//container/*/type[. &gt; 5]"><!--//container/*/type[. > 5]--></iso:assert>
      </iso:rule>
   </iso:pattern>
</iso:schema>