【问题标题】:Converting XML Node Names to Uppercase (XSLT 1.0)将 XML 节点名称转换为大写 (XSLT 1.0)
【发布时间】:2011-09-24 23:39:35
【问题描述】:

我有许多 XSLT 样式表可以将一些 XML 转换为 csv 文件。 使用的 XML 文件是根据数据库列名生成的,这些列名在构建 XML 时会自动转换为大写 - 现在无法再这样做(我们不使用 TSQL-FOR XML 来构建 XML)。列名通常是大写和小写字母的混合。 由于当前所有样式表都引用大写列名,因此 XPath 查询失败。

而不是遍历所有 XSL 样式表并手动将 XPath 查询更改为数据库列名的大小写——这将花费今年的大部分时间(!) 有什么方法可以将所有 XML 'Tag' 名称转换为大写,以便在文档中使用它们?

非常感谢任何帮助!

谢谢! 安德鲁

一个例子: 下面将生成一个 csv 文件,其中包含大约行数,但没有任何数据,因为 xslt 正在寻找“STRNAME”,当它作为“strName”存储在 XML 中时 我的 XML:

<XMLWRAPPER>
   <STAFFTABLE>
      <ROW>
         <strName>Andrew</strName>
         <strSurname>Smith</strSurname>
         <intuserType>1</intUserType>
      </ROW>
      <ROW>
         <strName>Jackie</strName>
         <strSurname>collins</strSurname>
         <intuserType>2</intUserType>
      </ROW>
    </STAFFTABLE>
  </XMLWRAPPER>

和 xslt:

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

<xsl:template match="/">"First Name","Surname","User type"<xsl:text>&#013;</xsl:text>

    <xsl:for-each select="/XMLWRAPPER/STAFFTABLE/ROW">
        <xsl:value-of select="STRNAME"/>,<xsl:value-of select="STRSURNAME"/>,<xsl:value-of select="INTUSERTYPE"/><xsl:text>&#013;</xsl:text>
     </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

【问题讨论】:

  • 根据您的数据库,将列名设为全大写也可以。另一种方法是在生成的 XML 上运行一个简单的 perl 脚本以大写标签。
  • 好问题,+1。请参阅我的解决方案,了解即使在名称包含非拉丁字母的情况下也可以使用的解决方案。

标签: xml xslt translate


【解决方案1】:

在 XSLT 1.0 中,我将使用 Identity Transformationtranslate() 函数:

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

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="*">
        <xsl:element name="{
            translate(name(.),
            'abcdefghijklmnopqrstuvwxyz',
            'ABCDEFGHIJKLMNOPQRSTUVWXYZ')}">
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

这种转换只会“大写”元素,而不是属性。无论如何,只需将第二个模板的匹配模式更改为*|@*,就可以轻松地将其扩展到属性。


根据下面的 cmets 和 specstranslate() 函数不是所有语言中大小写转换的充分解决方案。

【讨论】:

  • 太好了,谢谢。幸运的是,数据库命名约定意味着没有非 ascii 字符,所以这应该没问题!但是,在对 CSV 文件运行转换之前,是否应该将其用作单独的转换?或者有没有办法将它们合并到一个转换中?
  • 好(进一步的)问题。你可以引入这个,但我认为你需要一个两遍函数。
  • 你能做到吗?最近有一个关于此的线程,我为此提供了扩展答案。见this。如果您需要任何帮助,请告诉我。希望您满意后接受答案。
  • 嗨,Empo,你说的两遍函数是什么意思?
  • 谢谢Empo,我会试试看的:)
【解决方案2】:

@empo 的解决方案是在名称仅由拉丁字符组成的情况下可以使用的解决方案。如果不是这种情况,可以使用类似的 XSLT 2.0 转换,将 @empo 解决方案中的 translate() 函数替换为标准 XPath 2.0 函数 upper-case()

此外,如果您只有几个样式表,修改样式表本身以处理大小写混合的名称可能会容易得多:

即:

代替

&lt;xsl:template match="SOMENAME"&gt;

使用

 <xsl:template 
   match="*['SOMENAME' = translate(., $Lowercase, $Uppercase)]">

【讨论】:

  • 您对拉丁语的看法是绝对正确的 - 默认的 utf8 不会捕获所有内容 - 我住在丹麦,甚至没有代表 ÆØÅ。但是话又说回来,语言环境似乎是拉丁语:)
  • @user639175:upper-case() 函数在大多数情况下应该提供正确的结果。在少数例外情况下,它的结果与给定语言的语言期望不匹配 - 请参阅函数规范 - 在我的答案中链接到。
  • “如果不是这种情况”可以在 XSLT 1.0 中使用什么(这似乎是 OP 的情况)?
  • @empo:扩展字符串包含所有被认为是“下”的字母和所有被认为是“上”的字母——或者扩展函数,如果所有语言的所有字母都可以预期。然后将它们与translate() 一起使用
猜你喜欢
  • 2014-07-16
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 2021-08-08
  • 1970-01-01
相关资源
最近更新 更多