Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.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 如何使用XSLT v1.0插入文本,而不是使用XSLT v2.0正则表达式?_Java_Xml_Regex_Xslt - Fatal编程技术网

Java 如何使用XSLT v1.0插入文本,而不是使用XSLT v2.0正则表达式?

Java 如何使用XSLT v1.0插入文本,而不是使用XSLT v2.0正则表达式?,java,xml,regex,xslt,Java,Xml,Regex,Xslt,我有一个xml文件,它用描述完全限定java类名的属性值来描述(除其他外)元素。我试图编写一个XSLT转换来修改这个文件中描述的类名,例如,com.example.MyClass的ocurrance将变成com.example.MockMyClass 下面是在原始文件片段的上下文中再次出现的示例: <event type="node-enter"> <action name="MyActionName" class="com.example.MyClass">

我有一个xml文件,它用描述完全限定java类名的属性值来描述(除其他外)元素。我试图编写一个XSLT转换来修改这个文件中描述的类名,例如,
com.example.MyClass
的ocurrance将变成
com.example.MockMyClass

下面是在原始文件片段的上下文中再次出现的示例:

<event type="node-enter">
  <action name="MyActionName" class="com.example.MyClass">
    <bodyTemplate>
      templates/MyTemplate.vm
    </bodyTemplate>
  </action>
</event>

是一个开始,但我需要在匹配的字符串中插入文本,而不仅仅是替换

以下是我的正则表达式(XSLT 2.0)尝试,以供参考:


嘲弄

以下内容如何

<xsl:template name="classname">
    <xsl:param name="class"/>
    <xsl:choose>
        <xsl:when test="contains($class,'.')">
            <xsl:value-of select="concat(substring-before($class,'.'),'.')"/>
            <xsl:call-template name="classname">
                <xsl:with-param name="class"
                                    select="substring-after($class,'.')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="concat('Mock',$class)"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

它将类名作为输入参数,并在最后的“.”之后添加“Mock”。例如,你可以用

 <xsl:call-template name="classname">
     <xsl:with-param name="class" select="@class"/>
 </xsl:call-template>


(我只是在Firefox中快速试用了一下,你可能会发现你需要整理一些空白。)

下面的内容似乎很长,但是它使用了现成的部分(strRev
模板由FXSL提供,不需要重新编写)。此外,将近一半的代码是标识模板,并将参数传递给
。这在XSLT2.0中被大大缩短了

当我们准备好更小的部件/函数,比如
strRev
template/
reverse()
函数时,这个解决方案就不需要编写长时间且容易出错的自制递归代码

基本思想是字符串中的最后一个
字符是反向字符串中的第一个
字符

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pPrepend" select="'Mock'"/>
 <xsl:variable name="vRevPrepend">
  <xsl:call-template name="strRev">
   <xsl:with-param name="pText" select="$pPrepend"/>
  </xsl:call-template>
 </xsl:variable>


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

 <xsl:template match="action/@class">
   <xsl:variable name="vRevText">
    <xsl:call-template name="strRev"/>
   </xsl:variable>

   <xsl:variable name="vRevNew" select=
   "concat(substring-before($vRevText,'.'), $vRevPrepend,
           '.', substring-after($vRevText,'.'))"/>

   <xsl:variable name="vNewText">
     <xsl:call-template name="strRev">
      <xsl:with-param name="pText" select="$vRevNew"/>
     </xsl:call-template>
   </xsl:variable>

  <xsl:attribute name="class">
   <xsl:value-of select="$vNewText"/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template name="strRev">
  <xsl:param name="pText" select="."/>

  <xsl:if test="string-length($pText)">
   <xsl:call-template name="strRev">
    <xsl:with-param name="pText" select="substring($pText,2)"/>
   </xsl:call-template>
   <xsl:value-of select="substring($pText,1,1)"/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的XML文档时

<event type="node-enter">
  <action name="MyActionName" class="com.example.MyClass">
    <bodyTemplate>
      templates/MyTemplate.vm
    </bodyTemplate>
  </action>
</event>
<event type="node-enter">
    <action name="MyActionName" class="com.example.MockMyClass">
        <bodyTemplate>
          templates/MyTemplate.vm
        </bodyTemplate>
    </action>
</event>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:param name="pPrepend" select="'Mock'"/>

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

    <xsl:template match="action/@class">
     <xsl:attribute name="class" select=
     "my:strRev(concat(substring-before(my:strRev(.),'.'),
                       my:strRev($pPrepend),'.',
                       substring-after(my:strRev(.),'.')
                       )
                )
     "/>
    </xsl:template>

    <xsl:function name="my:strRev" as="xs:string">
      <xsl:param name="pText" as="xs:string"/>

      <xsl:sequence select=
       "codepoints-to-string(reverse(string-to-codepoints($pText)))
       "/>
    </xsl:function>
</xsl:stylesheet>

模板/MyTemplate.vm
生成所需的正确结果

<event type="node-enter">
  <action name="MyActionName" class="com.example.MyClass">
    <bodyTemplate>
      templates/MyTemplate.vm
    </bodyTemplate>
  </action>
</event>
<event type="node-enter">
    <action name="MyActionName" class="com.example.MockMyClass">
        <bodyTemplate>
          templates/MyTemplate.vm
        </bodyTemplate>
    </action>
</event>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:param name="pPrepend" select="'Mock'"/>

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

    <xsl:template match="action/@class">
     <xsl:attribute name="class" select=
     "my:strRev(concat(substring-before(my:strRev(.),'.'),
                       my:strRev($pPrepend),'.',
                       substring-after(my:strRev(.),'.')
                       )
                )
     "/>
    </xsl:template>

    <xsl:function name="my:strRev" as="xs:string">
      <xsl:param name="pText" as="xs:string"/>

      <xsl:sequence select=
       "codepoints-to-string(reverse(string-to-codepoints($pText)))
       "/>
    </xsl:function>
</xsl:stylesheet>

模板/MyTemplate.vm
II。XSLT 2.0解决方案

<event type="node-enter">
  <action name="MyActionName" class="com.example.MyClass">
    <bodyTemplate>
      templates/MyTemplate.vm
    </bodyTemplate>
  </action>
</event>
<event type="node-enter">
    <action name="MyActionName" class="com.example.MockMyClass">
        <bodyTemplate>
          templates/MyTemplate.vm
        </bodyTemplate>
    </action>
</event>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:param name="pPrepend" select="'Mock'"/>

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

    <xsl:template match="action/@class">
     <xsl:attribute name="class" select=
     "my:strRev(concat(substring-before(my:strRev(.),'.'),
                       my:strRev($pPrepend),'.',
                       substring-after(my:strRev(.),'.')
                       )
                )
     "/>
    </xsl:template>

    <xsl:function name="my:strRev" as="xs:string">
      <xsl:param name="pText" as="xs:string"/>

      <xsl:sequence select=
       "codepoints-to-string(reverse(string-to-codepoints($pText)))
       "/>
    </xsl:function>
</xsl:stylesheet>
完全相同的算法,但在XSLT 2.0中非常简短

<event type="node-enter">
  <action name="MyActionName" class="com.example.MyClass">
    <bodyTemplate>
      templates/MyTemplate.vm
    </bodyTemplate>
  </action>
</event>
<event type="node-enter">
    <action name="MyActionName" class="com.example.MockMyClass">
        <bodyTemplate>
          templates/MyTemplate.vm
        </bodyTemplate>
    </action>
</event>
<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:param name="pPrepend" select="'Mock'"/>

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

    <xsl:template match="action/@class">
     <xsl:attribute name="class" select=
     "my:strRev(concat(substring-before(my:strRev(.),'.'),
                       my:strRev($pPrepend),'.',
                       substring-after(my:strRev(.),'.')
                       )
                )
     "/>
    </xsl:template>

    <xsl:function name="my:strRev" as="xs:string">
      <xsl:param name="pText" as="xs:string"/>

      <xsl:sequence select=
       "codepoints-to-string(reverse(string-to-codepoints($pText)))
       "/>
    </xsl:function>
</xsl:stylesheet>


@Ryan,你的正则表达式中的
$
是用来做什么的?若它应该匹配行尾或字符串尾,那个么它不会失败吗,因为它后面必须跟一个字母数字?如果是这样的话,这似乎是多余的。但也许我误解了。@LarsH的
$
是为了迎合内部类,例如
com.example.MyClass$internal
。但是我现在看到这个正则表达式也会匹配一个字符串,比如
com$example.MyClass
,所以如果我继续使用正则表达式解决方案,我需要修复这个错误。@Ryan Bennetts:您需要通过
$
标记吗?或者只是通过
?@Ryan好的,谢谢。我忘了
[]
中的
$
是一个文本。内部类使用了
$
符号+1。请注意,对于类名不包含
的基本情况,它会给出不同的结果,但是这种情况在实践中可能不会发生。+1-您可以通过在
中包装文本节点,而不是在模板中“裸”挂起,来避免一些空白问题。这样,您就可以格式化代码,而不必担心模板中的回车符和其他空格会潜入到输出中。只有在空白字符前面或后面有非空白字符时,空白字符才被视为有效字符。用
换行将用于输出的文本内容与格式化空白区分开。谢谢,我不知道这一点。@Matthw Wilson:+1回答得好。这不处理内部类,例如
com.example.MyClass$internal
,但这在现阶段对我来说并不重要。我很难找到正确的上下文来调用您的模板,但最终通过匹配
上的“action/@class”
并使用
调用模板找到了答案,谢谢!我不能说我已经完全掌握了您的代码,但是看起来您已经硬编码了“MockMyClass”作为转换后的类名。然而,我想做的是在类名前面加上“Mock”一词,这样-例如-
com.example.ExampleClass
变成
com.example.MockExampleClass
com.example.AnotherExampleClass
当然了,这是最简单的事情——只需等待20分钟即可。:)谢谢Dimitre,你的代码运行得很好,但我还是选择了Matthew Wilson的解决方案,因为它更简洁。@Ryan Bennetts:作为一个消费者,它对你来说应该是一样的,但是如果你是一个开发人员,我的解决方案是一种可以节省大量时间和错误的设计模式——您只需使用现成的函数/模板,无需编写自己的递归代码。字符串反转正是解决路径
/content/art/VO1113VIEW05.01.tif
问题的方法,我需要在路径中去掉
.tif
,而不是
.05.tif