我正在尝试使用正则表达式修复一些双语xml文件,以匹配已知的错误内容模式并替换正确的值。 xml文件中的大多数问题都可以被视为拼写错误或冗余数据。
我确实有一个文本处理工具可以在没有任何正则表达式支持的情况下在软件中工作,但是如果我可以使用sed或类似的东西来编写批处理作业并将其留在一夜之间,那么整个情况将会变得如此简单。 应解决问题的示例sed脚本可能如下所示:
#!/bin/sed -f
s/<prop type="Att::Status">New/<prop type="Att::Status">Not Validated/g
s/<prop type="Att::Status">Approved/<prop type="Att::Status">Validated/g
....
我发现sed不喜欢UTF16文件,而且由于我们处理34种不同语言组合的双语xml,使用像iconv这样的工具来包装sed脚本可能非常危险。大多数字符集转换工具都会导致某些类型的损坏,我宁愿不花一周的时间来决定脚本正常运行的语言。
值得一提的是,xml充满了过去几年客户端的累积翻译,因此会有大量错误的语法,可能会绊倒一些工具。
总而言之,sed + iconv风险太大,我有一个基本的全局文本替换工具,我有Notepad ++,我甚至在sed语法中有一个替换表达式列表。但是有更简单/更好的方法吗?
答案 0 :(得分:1)
见XMLStarlet。它是用于读取/操作XML的命令行工具集。
特别是,xml ed命令可能就是你想要的。您可以指定要更改的内容的XPath,以及如何更改它。它将遵循指定的XML字符编码等,而标准命令行工具则不会这样。
答案 1 :(得分:1)
我不知道XML Starlet的复杂性是否比XSLT的复杂性要小 - 大多数复杂性实际上都在XPath中,您将用它来查找您将要更改的节点
如果您要使用XSLT,您只需创建一个身份转换,然后添加一个模板来更改您感兴趣的文本节点:
<xsl:template match="prop[@type='Att::Status']/text()">
<xsl:choose>
<xsl:when test=". = 'New'">Validated</xsl:when>
<xsl:when test=". = 'Approved'">Not Validated</xsl:when>
<xsl:otherwise>
<xsl:copy/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
或者您可以坚持并在外部XML文件中指定映射,例如:
<map>
<text value="New">Validated</text>
<text value="Approved">Not Validated</text>
</map>
然后,在你的XSLT中:
<xsl:variable name="map" select="document('map.xml')/map/text"/>
<xsl:template match="prop[@type='Att::Status']/text()">
<xsl:choose>
<xsl:when test="$map[@value=current()]">
<xsl:copy-of select="$map[@value=current()]/text()"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
答案 2 :(得分:0)
我认为xslt是你最好的选择。