1

类似于我之前遇到的一个问题,你们在不到一天的时间内就解决了。

我正在处理由数码摄像机生成的 XML 文件。相机允许用户将相机的所有设置保存到 SD 卡中,以便可以调用设置或将设置加载到另一台相机中。我正在编写的 XSL 样式表将允许用户查看相机的设置,这些设置保存在 Web 浏览器中的 SD 卡中。

虽然 XML 文件中的大多数值(由我的样式表格式化)对人类来说是有意义的,但有些则不然。我想做的是让样式表显示文本基于 XML 文件中的值,但更容易被人类理解。

可以写入 XML 文件的典型值是“_23_970”,它表示相机的帧速率。这将更好地显示为 23.970(或 023.970)。第一个下划线是一种占位符,为超过 099.999 的值留出空间。第二个下划线,显然代表小数。

我之前的(类似)问题涉及替换可预测的文本,解决方案是匹配模板。然而,在这种情况下,相机可以设置为 119,999 帧速率中的任何一个(我认为我的计算是正确的)。

我猜这种方法是将一个值传递给显示的网页,该网页保留数值(每个数字),用小数替换第二个下划线,并用 nbsp 或零替换第一个下划线(以更容易的为准) )。如果字符串中的第一个字符是“1”(相机可以以高达 120.000 的帧速率运行),则应将其传递到样式表显示的页面。

我在这里阅读了有关通配符的其他帖子,但找不到回答这个问题的帖子。

编辑:很抱歉遗漏了重要信息。我在第一次尝试提问时表现得更好!我想我得意了。无论如何。. .

我应该向您展示在 XSL 文件中显示文本的代码:

<tr>
  <xsl:for-each select="Settings/Groups/Recording">
    <tr><td class="title_column">Frame Rate</td><td><xsl:value-of select="RecOutLinkSpeed"/></td></tr>
   </xsl:for-each>
</tr>

我还应该给你我一直在使用的示例文件的 URL:http: //josephthomas.info/Alexa/Setup_120511_140322.xml

4

2 回答 2

3

假设具有这些值的元素被命名frame-rate为以下使用模板来处理两种情况:

<xsl:template match="frame-rate[starts-with(., '_')]">
  <xsl:value-of select="concat('&#160;', translate(substring(., 2), '_', '.'))"/>
</xsl:template>

<xsl:template match="frame-rate[not(starts-with(., '_'))]">
  <xsl:value-of select="translate(., '_', '.')"/>
</xsl:template>
于 2012-06-22T17:31:09.620 回答
1

使用

concat(translate(substring(.,1,1), '_', '&#xA0;'),
       translate(substring(.,2), '_', '.')
      )

这是一个完整的转换:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <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=
  "td[preceding-sibling::*[1][self::td and . = 'Frame Rate']]/text()">
  <xsl:value-of select=
   "concat(translate(substring(.,1,1), '_', '&#xA0;'),
           translate(substring(.,2), '_', '.')
          )
   "/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于一个简单的 XML 文档时,该文档包含tr来自实际 XML 文档的一个实际元素(并添加一个以测试第二种情况),如提供的链接所指

<t>
    <tr>
        <td class="title_column">Frame Rate</td>
        <td>_23_976</td>
    </tr>
    <tr>
        <td class="title_column">Frame Rate</td>
        <td>118_235</td>
    </tr>
</t>

产生了想要的正确结果:

<t>
   <tr>
      <td class="title_column">Frame Rate</td>
      <td> 23.976</td>
   </tr>
   <tr>
      <td class="title_column">Frame Rate</td>
      <td>118.235</td>
   </tr>
</t>

说明

表达方式:

concat(translate(substring(.,1,1), '_', '&#xA0;'),
       translate(substring(.,2), '_', '.')
      )

通过以下方式进行评估:

  1. 函数的两个参数concat()分别计算(彼此独立)。

  2. concat()就像它的名字所暗示的那样——将它的两个字符串参数连接成一个字符串。

  3. translate()函数在此表达式中被引用了两次——它用于生成 `concat() 的每个参数。

  4. 的第一个调用translate()是:translate(substring(.,1,1), '_', '&#xA0;')。在这种情况下,传递给函数的第一个参数是当前节点的字符串值的前导字符(在 XPath 中,当前(或上下文)节点由 表示.)。这个前导字符是由函数调用产生的:substring(.,1,1)它接受一个从偏移量 1 开始并且长度为 1的子字符串translate()。这个调用的第二个参数是一个包含我们想要替换或删除的所有字符的字符串——在这种情况下只是单个"_"字符。第三个参数translate()是一串“替换字符”,应该替换第二个参数中对应的(按位置)字符。在这种情况下,第三个参数包含单个字符'&#xA0;'(nbsp),这意味着对translate()函数的调用会将当前节点的字符串值的第一个字符替换为nbsp ,如果它恰好是一个下划线。

  5. 第二个调用translate()类似于第一个调用:translate(substring(.,2), '_', '.'). 但是,它将应用于当前节点的字符串值的剩余部分(从位置 2 开始),并用点字符替换该剩余部分中的任何下划线。

更新

由于 OP 难以理解如何将此解决方案调整为他自己的代码。这是我的猜测(因为他的源 XML 文档不是所提供的链接所指向的文档,我无法猜测真正的 XML 文档是什么):

<tr>
    <xsl:for-each select="Settings/Groups/Recording">
        <tr>
            <td class="title_column">Frame Rate</td>
            <td>
          <xsl:value-of select=
           "concat(translate(substring(RecOutLinkSpeed,1,1), '_', '&#xA0;'),
                   translate(substring(RecOutLinkSpeed,2), '_', '.')
                  )
           "/>
            </td>
        </tr>
    </xsl:for-each>
</tr>
于 2012-06-23T01:47:55.210 回答