【问题标题】:Capitalize all XML attribute names将所有 XML 属性名称大写
【发布时间】:2015-12-24 01:56:07
【问题描述】:

假设我有以下 XML:

 <DataDictionary numberOfFields="5">
  <DataField name="Species" optype="categorical" dataType="string">
   <Value value="setosa"/>
   <Value value="versicolor"/>
   <Value value="virginica"/>
  </DataField>
  <DataField name="Sepal.Length" optype="continuous" dataType="double"/>
  <DataField name="Sepal.Width" optype="continuous" dataType="double"/>
  <DataField name="Petal.Length" optype="continuous" dataType="double"/>
  <DataField name="Petal.Width" optype="continuous" dataType="double"/>
 </DataDictionary>

有人可以提供一个将所有属性名称大写的正则表达式(例如,对于 vim 或 sed)吗?

例如,我希望numberOfFields 成为NumberOfFieldsdataType 成为DataType

【问题讨论】:

  • 你的预期输出是什么?

标签: regex xml vim sed


【解决方案1】:

使用 sed 处理 XML 通常不是一个好主意,因为 sed 以基于行的方式工作,而 XML 并不真正关心换行符。例如,您可以拥有

<foo bar=
   "baz"/>

在完全有效的 XML 中,这将很难用 sed(或其他纯文本工具)处理。

我建议使用 XSLT 样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
  <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

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

  <xsl:template match="@*">
    <xsl:variable name="capname"
                  select="concat(translate(substring(name(.),1,1), $vLower, $vUpper), substring(name(.), 2))"/>
    <xsl:attribute name="{$capname}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

把它放在一个文件中,比如foo.xsl,然后使用一个XSLT处理器比如xsltproc来运行它:

xsltproc foo.xsl foo.xml

foo.xml 是您的 XML 文件。或者,使用xalan

xalan -xsl foo.xsl -in foo.xml

任何 XSLT 处理器都可以;对于其他人,请查看他们的联机帮助页。

它的工作原理如下:

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

是适用于所有节点的identity transform(在这种情况下不是属性,因为它们在其他地方处理)并递归地应用模板。这使得转换的输出是输入的副本,没有其他模板适用。肉在

  <xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
  <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

  <xsl:template match="@*">
    <xsl:variable name="capname"
                  select="concat(translate(substring(name(.),1,1), $vLower, $vUpper), substring(name(.), 2))"/>
    <xsl:attribute name="{$capname}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

这适用于所有属性 (@*)。

concat(translate(substring(name(.),1,1), $vLower, $vUpper), substring(name(.), 2))

是属性名称的大写版本,它被分配给变量capname。那么

<xsl:attribute name="{$capname}">
  <xsl:value-of select="."/>
</xsl:attribute>

插入具有大写名称和旧值的新属性来代替旧的非大写属性。

这适用于所有有效的 XML 输入。

【讨论】:

  • 谢谢。这是一个完整的解决方案。另外,感谢您将我指向 xsltproc。
【解决方案2】:

使用适当的 XML 处理工具,sed 无法轻松处理所有可能的 XML 语法规则。

xsh,一个XML编辑shell为例:

open file.xml ;
rename { ucfirst } //@* ;
# OR, to avoid any Perl:
# rename xsh:ucfirst(name()) //@* ;
save :b ;

【讨论】:

  • 哦,那很好。我得仔细看看 xsh2。
猜你喜欢
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 2013-07-27
  • 1970-01-01
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
相关资源
最近更新 更多