输出名称为文本的版本

时间:2012-06-21 12:43:14

标签: xml xslt xslt-1.0

这是我输入的xml。 xml可以有最多三个节点和最少1个节点。最小节点,输入xml可以有,如下所示

<Root>
   <node>uniquename</node>
</Root>

最大节点,输入xml可以有以下。包含节点的Uniquename将始终存在。

我的样本输入xml,用于下面的样本所需输出

<Root>
   <node>abc</node>
   <node>e1</node>
   <node>uniquename2</node>
</Root>

值'abc'对于所有输入xmls都是通用的。值e1,就像版本号。它可以有e1到e9。它也可以有一个小版本,如e1.1到e9.9。第三个节点是唯一的。我的输出应该是下面的文本,下面的样本作为所需的输出

Unique name with version from the xml - uniquename2e1
version number - e1
common name - Present in the input

输入xml节点的顺序各不相同,即有时版本号可以位于顶部,有时唯一名称可以位于顶部。通用名称也是如此。不过我的输出应该是uniquename后跟版本号。如果输入xml中没有通用名称,则输出文本应指示,它不存在

如果输入中没有版本号,则输出中的版本号行可以为空白

Unique name with version from the xml - uniquename3
common name - Present/Absent in the input.

虽然我没有xslt 2.0处理器,但是我的xslt处理器支持xmlns:regexp =“http://exslt.org/regular-expressions”,我想用它来查找版本控制部分。

编辑

唯一名称不符合版本号模式^e\d(\.\d)*$或不符合通用名称

2 个答案:

答案 0 :(得分:1)

此XSLT 1.0转换

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my">
     <xsl:output method="text"/>

     <my:commonAbsent/>

     <xsl:variable name="vVer" select=
      "/*/node
           [starts-with(., 'e')
          and
           number(substring(.,2)) = number(substring(.,2))]"/>

     <xsl:template match="/*">
      <xsl:apply-templates mode="unique" select=
       "node[not(. = 'abc'
                or
                 generate-id() =generate-id($vVer)
                 )
             ]"/>
      <xsl:apply-templates select="$vVer" mode="ver"/>

      <xsl:apply-templates select=
       "node[. = 'abc']
       |
        document('')
           [not(current()/node[.='abc'])]
                        /*/my:commonAbsent
       "/>
     </xsl:template>

     <xsl:template match="node" mode="unique">
     Unique name with version from the xml - <xsl:text/>

     <xsl:value-of select="concat(., $vVer)"/>
     </xsl:template>

     <xsl:template match="node" mode="ver">
     Version number - <xsl:value-of select="$vVer"/>
     </xsl:template>

     <xsl:template match="node[. = 'abc']">
     Common name - Present in the input
     </xsl:template>

     <xsl:template match="my:commonAbsent">
     Common name - Absent in the input
     </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<Root>
    <node>abc</node>
    <node>e1</node>
    <node>uniquename2</node>
</Root>

生成想要的正确结果

 Unique name with version from the xml - uniquename2e1
 Version number - e1
 Common name - Present in the input

对没有“通用名称”的XML文档应用相同的转换时:

<Root>
    <node>e1</node>
    <node>uniquename2</node>
</Root>

再次产生正确的,想要的结果:

 Unique name with version from the xml - uniquename2e1
 Version number - e1
 Common name - Absent in the input

最后,如果XML文档中没有表示“版本”:

<Root>
    <node>abc</node>
    <node>uniquename2</node>
</Root>

再次应用相同的转换会产生想要的正确结果:

 Unique name with version from the xml - uniquename2
 Common name - Present in the input

<强>解释

结果树中节点的顺序(在这些情况下所有节点都是文本节点)完全由xsl:apply-templates指令的顺序决定,这些指令选择执行生成这些结果树节点的模板

答案 1 :(得分:0)

我没有对此进行测试,因为我无法访问EXSLT,但此样式表应该可以正常工作.. 此脚本还有很多改进的余地,比如将节点放入变量中以便不必重复计算它们并使用xsl:choose而不是xsl:if和xsl:if on a not(condition) 。所以请考虑这个快速而肮脏的版本。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:regexp="http://exslt.org/regular-expressions"
  extension-element-prefixes="regexp">
<xsl:import href="regexp.xsl" />    
<xsl:output method="text" />

<xsl:template match="/">
<xsl:value-of select="Root/node[.!='abc'][regexp:test(.,'^e\d(\.\d)*$','')]" /><xsl:value-of select="Root/node[regexp:test(.,'^e\d(\.\d)*$','')]" /> 
<xsl:if test="Root/node[regexp:test(.,'^e\d(\.\d)*$','')]">
version number - <xsl:value-of select="Root/node[regexp:test(.,'^e\d(\.\d)*$','')]" />
</xsl:if>  
<xsl:if test="Root/node[.='abc']">
common name - Present in the input
</xsl:if>  
<xsl:if test="not( Root/node[.='abc'])">
common name - Absent in the input
</xsl:if>  
</xsl:template>

</xsl:stylesheet>