【问题标题】:Output the version with name as text以文本形式输出带有名称的版本
【发布时间】:2012-06-21 12:43:14
【问题描述】:

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

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

输入xml可以有的最大节点数如下。包含唯一名称的节点将始终存在。

以下示例所需输出的示例输入 xml

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

值“abc”对于所有输入 xml 都是通用的。 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 节点的顺序各不相同,即有时版本号可能位于顶部,有时唯一名称可能位于顶部。通用名称也是如此。不过,我的输出应该有唯一名称,后跟版本号。如果输入 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)*$ 或不是通用名称的东西

【问题讨论】:

  • Suresh:如果您说“Uniquename 绝对不遵循任何模式”,那么可能无法从这两个节点值中确定:"e10" 和 "e11" 哪个是版本,哪个是是唯一值。请编辑问题,以消除这种矛盾。
  • 所以我对规则的理解是这样的:如果节点值正好是'abc',那么它就是公共节点。如果节点值与正则表达式 '^e\d(\.\d)?$' 匹配,则它是版本节点。如果节点不是这两个节点,那么它就是“唯一名称”节点。这是正确的吗?
  • @DimitreNovaatchev 。唯一名称将包含除通用名称或版本号模式之外的任何内容。我的问题模棱两可。
  • Suresh:既然这不矛盾,我已经回答了这个问题。对你有用还是你还有问题?

标签: xml xslt xslt-1.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 指令的顺序决定,这些指令选择执行生成这些结果树节点的模板。

【讨论】:

    【解决方案2】:

    我没有对此进行测试,因为我无法访问 EXSLT,但是这个样式表应该可以工作.. 此脚本还有很多改进空间,例如将节点放入变量中,这样它们就不必重复计算,并在 not( 条件下使用 xsl:choose 代替 xsl:if 和 xsl:if ) .所以认为这是快速而肮脏的版本。

    <?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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 2017-05-07
      • 1970-01-01
      • 2022-11-20
      • 1970-01-01
      相关资源
      最近更新 更多