xml - 如何在 VBA 中替换 XML 文件的 unicode 字符
问题描述
问题:包含“en dash”、“em dash”的 XML 文件的目录必须替换为常规的 ASCII 字符破折号。还有单/双左/右大引号,必须用 ASCII 字符直单/双引号替换。
由于工作限制,此处只能使用基于 microsoft 的计算机上的 VBA(无法访问 powershell、脚本语言、java 等。)
我知道 VBA 可以解释 Unicode 字符,但是它不能写 unicode 字符。而不是编写 unicode 字符,而是将其替换为垃圾(即 Ite$&s,其中“e$&”是垃圾,输出应该是“It's”)
我尝试使用字符串操作的示例:
伪代码:
- 将 XML 内容转换为字符串
- 如果找到 Unicode 字符“破折号”,则
-
- 替换为 ASCII 破折号/连字符
- 写入 XML 文件
示例 XML:(前两个破折号分别是 en-dash 和 em-dash 在堆栈溢出时未正确显示)
<para> TEST REPLACE UNICODE CHARACTERS: — – - “ ” ‘ ’ '</para>
示例 VBA 输出:
<para> TEST REPLACE UNICODE CHARACTERS: â€" â€" - “ â€� ‘ ’ '</para>
代码:
Const ForReading = 1
Const TristateTrue = -1
Dim FSO As Object: Set FSO = CreateObject("Scripting.FileSystemObject")
Dim XMLString As String
XMLString = FSO.OpenTextFile(FilePath, ForReading, TristateTrue).ReadAll
UpdatedXMLString = Replace(XMLString, ChrW(8211), Chr(45)) 'Replace En-Dash
UpdatedXMLString = Replace(UpdatedXMLString, ChrW(8212), Chr(45)) 'Replace Em-Dash
UpdatedXMLString = Replace(UpdatedXMLString, ChrW(8220), Chr(34)) 'Replace Left Double Curly
UpdatedXMLString = Replace(UpdatedXMLString, ChrW(8221), Chr(34)) 'Right Double Curly
Set objStream = CreateObject("ADODB.Stream")
objstream.Charset = "utf-8"
objstream.Open
objStream.WriteText UpdatedXMLString
objStream.SaveToFile UpdatedFilePath, 2
我的经验:
我知道文件中存在一个 En Dash 的事实,但是该字符的替换不成功。关于 En/Em 破折号,我不输入“If 语句”的逻辑。但是,我确实成功输入了 Curly Quotes 的“If 语句”,但字符的替换不成功。
是否必须在“FSO.OpenTextFile().ReadAll”之前执行字符替换?在 XML 文件中用 ASCII 字符替换 Unicode 字符的适当代码流是什么?
解决方案
这是一个概念性的例子。
XSLT 正在使用该translate()
函数。
- 每个小写的“o”和“i”将被翻译/替换为相应的大写字母。
- 输入 XML 还具有mdash作为实体以使其可见。它被带有常规破折号的 XSLT 取代。
对于您的情况,您需要放置自己的字符以及需要替换的字符。
输入 XML
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
<!ENTITY mdash "—">
<!ENTITY ndash "–">
<!ELEMENT root (para)*>
<!ELEMENT para (#PCDATA)>
]>
<root>
<para>Miami</para>
<para>Orlando</para>
<para>Dog — pony</para>
</root>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="para">
<xsl:copy>
<xsl:value-of select="translate(., 'oi—', 'OI-')"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出 XML
<?xml version="1.0" encoding="utf-8"?>
<root>
<para>MIamI</para>
<para>OrlandO</para>
<para>DOg - pOny</para>
</root>
推荐阅读
- codenameone - 代号一:全双工通话
- cassandra - Cassandra-stress 不会为每一行生成随机值
- php - CodeIgniter 显示 MySQL 计数
- sql-server - 想要在 group by 子句中强制为零
- communication-protocol - 有没有基于单向UDP的容错协议?
- arrays - Swift 的 Javascript getUint16 替代品
- python - 在 Python 中通过细微更改覆盖方法的正确方法
- microsoft-translator - 上传到自定义翻译器时的文件大小限制
- r - 使用 R(求解器)最小化预算
- r - 即使代码编译,每个命令都会在 R 中给出几个警告