大写所有XML属性名称

sta*_*010 0 regex xml vim sed

假设我有以下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>
Run Code Online (Sandbox Code Playgroud)

有人可以为所有属性名称提供正则表达式(例如vim或sed)吗?

例如,我想numberOfFieldsNumberOfFieldsdataTypeDataType.

Win*_*ute 5

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

<foo bar=
   "baz"/>
Run Code Online (Sandbox Code Playgroud)

在完全有效的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>
Run Code Online (Sandbox Code Playgroud)

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

xsltproc foo.xsl foo.xml
Run Code Online (Sandbox Code Playgroud)

foo.xml你的XML文件在哪里.或者,用xalan:

xalan -xsl foo.xsl -in foo.xml
Run Code Online (Sandbox Code Playgroud)

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

其工作原理如下:

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

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

  <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>
Run Code Online (Sandbox Code Playgroud)

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

concat(translate(substring(name(.),1,1), $vLower, $vUpper), substring(name(.), 2))
Run Code Online (Sandbox Code Playgroud)

是属性名称的大写版本,并将其分配给变量capname.然后

<xsl:attribute name="{$capname}">
  <xsl:value-of select="."/>
</xsl:attribute>
Run Code Online (Sandbox Code Playgroud)

插入具有该大写名称的新属性和旧值以代替旧的非大写属性.

这将适用于所有有效的XML输入.