【问题标题】:XML PrettyPrint xslt transformXML PrettyPrint xslt 转换
【发布时间】: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。

标签: xml excel xslt vba


【解决方案1】:

有趣的是,如果我在 Notepad++ 中打开它,它会像我想要的那样缩进 2,但它会将编码更改为 utf-16。

<xsl:output method="xml" indent="yes" xalan:indent-amount="2"/>

您正在使用带有 Xalan 扩展的 MSXML。那是行不通的,因为 MSXML 对 Xalan 扩展一无所知。您在 Notepad++ 中看到 indent=2 的事实可能是因为您将其配置为在编辑器的设置中以这种方式缩进。在 Windows 的记事本中,您会看到正确的缩进 4。

请注意,从 XML 的角度来看,编码或缩进并不重要。这仅在人工阅读文件并且您更喜欢另一个缩进的情况下才重要,您也可以在 XML 编辑器、Visual Studio 或(实际上不是 XML 编辑器)Notepad++ 中进行配置。

如果我在记事本中打开它,它也会将编码更改为 utf-16,但不会更改间距。

“它改变了编码”是什么意思?仅当您再次保存文件时才会发生这种情况。

    Open sFileOut For Output As #ffile
       Print #ffile, PrettyPrintXML
   Close #ffile

由于您使用非 XML 方法编写文件,因此您几乎无法控制其编码。如果您想要某种编码,请直接从 XSLT 转换写入文件,即使用:

<xsl:output encoding="utf-8" />

并拥有MSXML save it for you,而不是将其写入字符串然后保存。

关于漂亮的打印(如果缩进本身还不够),请查看SO question and answer

【讨论】:

    猜你喜欢
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多