【发布时间】:2015-09-10 13:02:13
【问题描述】:
我正在使用 VBA 在 Excel 2010 中工作。我在 MS SQL Server 2008 数据库表中有一个列,其中包含一行 XML。我正在提取它并使用我编写的“漂亮打印”例程使其可读。我遇到的问题是它没有采用我在 xslt 转换中给出的值。正如你所看到的,我已经尝试了很多组合,我发现这些组合在不同的谷歌搜索中。代码如下:
Function PrettyPrintXML(strXML As String, Optional sFileOut As String) As String
Dim xDoc As MSXML2.DOMDocument60
Set xDoc = New MSXML2.DOMDocument60
Dim xDocStyle As MSXML2.DOMDocument60
Set xDocStyle = New MSXML2.DOMDocument60
Dim xDocOut As MSXML2.DOMDocument60
Set xDocOut = New MSXML2.DOMDocument60
Dim strXMLStyleSheet As String
strXMLStyleSheet = "<?xml version=""1.0"" encoding=""utf-8""?>" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & "<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform""" & vbCrLf
'strXMLStyleSheet = strXMLStyleSheet & " extension -element - prefixes = ""redirect""" & vbCrLf
'strXMLStyleSheet = strXMLStyleSheet & " xmlns:xalan=""http://xml.apache.org/xalan"">" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & " xmlns:xalan=""http://xml.apache.org/xslt"">" & vbCrLf
'strXMLStyleSheet = strXMLStyleSheet & "<xsl:output method=""xml"" encoding=""UTF-8"" indent=""yes"" xalan:indent-amount=""2""/>" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & "<xsl:output method=""xml"" indent=""yes"" xalan:indent-amount=""2""/>" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & "<xsl:strip-space elements=""*""/>" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & "<xsl:template match=""@* | node()"">" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & " <xsl:copy>" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & " <xsl:apply-templates select=""@* | node()""/>" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & " </xsl:copy>" & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & "</xsl:template>" & vbCrLf & vbCrLf
strXMLStyleSheet = strXMLStyleSheet & "</xsl:stylesheet>"
'strXMLStyleSheet = "<xsl:stylesheet xmlns:xsl=""http://www.w3.org/1999/XSL/Transform""" & vbCrLf
'strXMLStyleSheet = strXMLStyleSheet & "Version = ""1.0""" & vbCrLf
'strXMLStyleSheet = strXMLStyleSheet & "xmlns: redirect = ""http://xml.apache.org/xalan/redirect""" & vbCrLf
'strXMLStyleSheet = strXMLStyleSheet & "extension-element-prefixes = ""redirect""" & vbCrLf
'strXMLStyleSheet = strXMLStyleSheet & "xmlns:xalan=""http://xml.apache.org/xslt"">" & vbCrLf
'strXMLStyleSheet = strXMLStyleSheet & "<xsl:output method=""xml"" indent=""yes"" xalan:indent-amount=""2""/>" & vbCrLf
With xDocStyle
.async = False
.validateOnParse = False
.resolveExternals = False
DebugPrint strXMLStyleSheet
.LoadXML strXMLStyleSheet
End With
With xDoc
.async = False
.validateOnParse = False
.resolveExternals = False
DebugPrint strXML
.LoadXML strXML
.transformNodeToObject xDocStyle, xDocOut
End With
PrettyPrintXML = xDocOut.XML
If Not sFileOut = "" Then
If Not PrettyPrintXML = "" Then
Dim ffile As String
ffile = FreeFile
Open sFileOut For Output As #ffile
Print #ffile, PrettyPrintXML
Close #ffile
Else
MsgBox "No file was generated. Check your parameters and try again.", vbOKOnly, "Empty File"
End If
End If
Set xDocOut = Nothing
Set xDocStyle = Nothing
Set xDoc = Nothing
End Function
最新版代码中的xslt变换为:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml" indent="yes" xalan:indent-amount="2"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
有趣的是,如果我在 Notepad++ 中打开它,它会像我想要的那样缩进 2,但它会将编码更改为 utf-16。如果我在记事本中打开它,它也会将编码更改为 utf-16,但不会更改间距。我尝试将其更改为 utf-16 和 ASCII。不过没有变化。我的最终目标是让用户可以选择在记事本、写字板、MS Word 2010 或他们想要的任何自定义程序(如 Ultraedit、textedit、vi、Emacs 等)中打开它。不过,我必须先让它工作。
【问题讨论】:
-
您似乎正在将文档保存到打开的文本文件中。为什么不使用转换后的Save Method?同样在 xslt 的 output 标记中,您可以指定编码。
-
您使用的间距属性似乎是特定于 Xalan 的 - MSXML 怎么知道如何处理它?
-
虽然这并不完全是重复的,但您可以更轻松地在 VBA 中漂亮地打印 XML:stackoverflow.com/questions/1118576/…
-
@parfait 我将 sFileOut 设为可选,仅用于调试。当我调用代码时,我不使用它。我对 xslt 很陌生,所以我只是边学边学。感谢 cmets。