如何清理 XML 属性值

如何清理 XML 属性值

我有这样的 XML:

<string name="foo-bar">"bar-bar -bar"</string>
<string name="asdf_qwe-rty" translatable="false">"Lorem ipsum"</string>

现在,该name属性不能包含-字符,所以我想将其替换为_.

<string name="foo_bar">"bar-bar -bar"</string>
<string name="asdf_qwe_rty" translatable="false">"Lorem ipsum"</string>

我怎样才能做到这一点,最好是使用sed

答案1

假设 XML 文档格式良好,您可以使用以下方式替换所有节点属性中xmlstarlet出现的所有字符:-namestring_

$ xmlstarlet ed -u '//string/@name' -x 'translate(.,"-","_")' file.xml
<?xml version="1.0"?>
<root>
  <string name="foo_bar">"bar-bar -bar"</string>
  <string name="asdf_qwe_rty" translatable="false">"Lorem ipsum"</string>
  <string name="_test1_">name="-test1-"</string>
  <!-- <string name="-test2-">name="-test2-"</string> -->
</root>

(我在此处添加了一个包装root节点以使文档格式良好,并添加了一些额外的情况以表明我们不会影响节点值或注释内容)。

xmlstarlet表达式将使用 XPath 表达式 查找所有相关属性//string/@node,并将每个属性的简单转换-应用于_每个属性的值。输出被写入标准输出。

答案2

任何基于 sed 的解决方案(或任何其他不进行正确 XML 解析的解决方案)在一定比例的边缘情况下都会出错。例如@Pitel的解决方案:

(a) 替换看起来像名称属性的内容,即使它们位于注释或文本中而不是位于开始标记中

firstname(b) 还更改名为或的属性的内容lastname

(c) 如果等号周围有空格,则无法发现该属性。

因此,它可能足以满足一次性的临时使用,但不要将其放入生产工作流程中。如果您需要生产质量的东西,请使用 XSLT 转换。这并不难:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
  <xsl:mode on-no-match="shallow-copy"/>
  <xsl:template match="@name">
    <xsl:attribute name="name" select="translate(., '-', '_')"/>
  </xsl:template>
</xsl:transform>

答案3

sed -r ':a; s/(name="[^-"]*)-/\1_/; ta'

相关内容