问题:一个目录中充满了包含"en dash", "em dash"必须用常规的ASCII字符"破折号"替换。还有单/双左/右花引号,必须用ASCII字符的直单/双引号替换。
由于工作限制,这里只能使用微软计算机上的VBA(不能访问powershell,脚本语言,java等)
我已经学会了VBA可以解释Unicode字符,但它不能写Unicode字符。它不编写unicode字符,而是将其替换为垃圾字符(例如Ite$&s,其中"e$&"是垃圾,输出应该是"It's">
一个我尝试使用字符串操作的例子:
伪代码:
- 将XML内容转换为字符串
- If Unicode Character "en dash">
-
- 用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"语句的逻辑。但是,我确实成功地输入了"If语句"。对于大引号,但替换字符是不成功的。
字符的替换必须在"FSO.OpenTextFile().ReadAll"之前执行吗?在XML文件中用ASCII字符替换Unicode字符的适当代码流是什么?
这里有一个概念性的例子。
XSLT正在使用translate()
函数
- 每个小写的'o'和'i'将被翻译/替换为它们
- 输入XML也有mdash作为实体使其可见。它被替换了
对于您的情况,您需要放置您自己的字符,以及它们需要替换为。
输入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>
接受使用XSLT的建议,这里是一个VBScript示例,您应该能够转换为使用MSXML 6加载输入文档的VBA代码,应用XSLT样式表translate
在文本节点中的相关字符并将结果写回XML文件:
Set xmlDoc = CreateObject("Msxml2.DOMDocument.6.0")
xmlDoc.preserveWhitespace = True
xmlDoc.load "msxml-vb-input-sample1.xml"
Set xsltDoc = CreateObject("Msxml2.DOMDocument.6.0")
xsltDoc.load "msxml-vb-xslt-sample1.xsl"
Set resultDoc = CreateObject("Msxml2.DOMDocument.6.0")
xmlDoc.transformNodeToObject xsltDoc, resultDoc
resultDoc.save "msxml-vb-xslt-result-sample1.xml"
XSLT只是执行
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="input-chars">—–-“”‘’'</xsl:param>
<xsl:param name="output-chars">---""'''</xsl:param>
<xsl:output encoding="UTF-8"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of
select="translate(., $input-chars, $output-chars)"/>
</xsl:template>
</xsl:stylesheet>
然后转换,例如
<?xml version="1.0" encoding="UTF-8"?>
<para> TEST REPLACE UNICODE CHARACTERS: — – - “ ” ‘ ’ '</para>
<?xml version="1.0" encoding="UTF-8"?>
<para> TEST REPLACE UNICODE CHARACTERS: - - - " " ' ' '</para>
OpenTextFile有一个Format
参数,你可以提供设置UTF:
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/opentextfile-method: ~:文本= TristateTrue文件% 20 % 20 unicode。
如果不提供,则默认为ASCII。
另外,我相信你的原始文件可能需要保存为UTF-16