强制MSXML使用缩进和换行格式化XML输出

时间:2011-06-19 21:34:07

标签: vb6 msxml

我使用MSXML 3.0和Visual Basic 6来存储和检索我的应用程序的配置。将生成的DOMDocument保存到XML文件时,根对象将呈现为单个非常长的文本行:

<?xml version="1.0"?>
<!--WORKAPP 2011 Configuration file-->
<profile version="1.0"><frmPlan><left>300</left><top>300</top><width>24600</width><height>13575</height></frmPlan><preferences><text1/><text2/><text3/><background_color/><grid-major-step-x>50</grid-major-step-x><grid-major-step-y>50</grid-major-step-y></preferences></profile>

是否可以强制MSXML使用缩进和换行格式化生成的XML文件?

4 个答案:

答案 0 :(得分:8)

对于像配置这样的小文件,使用XSL的开销可能并不重要。当您处理大型文件或大量小型文件(如Web服务器的服务器端)时,SAX的功能更为重要 - 您可能不应该首先使用重量级DOM。

Private Sub FormatDocToFile(ByVal Doc As MSXML2.DOMDocument, _
                            ByVal FileName As String)
    'Reformats the DOMDocument "Doc" into an ADODB.Stream
    'and writes it to the specified file.
    '
    'Note the UTF-8 output never gets a BOM.  If we want one we
    'have to write it here explicitly after opening the Stream.
    Dim rdrDom As MSXML2.SAXXMLReader
    Dim stmFormatted As ADODB.Stream
    Dim wtrFormatted As MSXML2.MXXMLWriter

    Set stmFormatted = New ADODB.Stream
    With stmFormatted
        .Open
        .Type = adTypeBinary
        Set wtrFormatted = New MSXML2.MXXMLWriter
        With wtrFormatted
            .omitXMLDeclaration = False
            .standalone = True
            .byteOrderMark = False 'If not set (even to False) then
                                   '.encoding is ignored.
            .encoding = "utf-8"    'Even if .byteOrderMark = True
                                   'UTF-8 never gets a BOM.
            .indent = True
            .output = stmFormatted
            Set rdrDom = New MSXML2.SAXXMLReader
            With rdrDom
                Set .contentHandler = wtrFormatted
                Set .dtdHandler = wtrFormatted
                Set .errorHandler = wtrFormatted
                .putProperty "http://xml.org/sax/properties/lexical-handler", _
                             wtrFormatted
                .putProperty "http://xml.org/sax/properties/declaration-handler", _
                             wtrFormatted
                .parse Doc
            End With
        End With
        .SaveToFile FileName
        .Close
    End With
End Sub

答案 1 :(得分:3)

这个答案可能对你的具体情况没有帮助,但总的来说它可能有用。它考虑了在没有太多修改的情况下加载和保存文档的情况。 DomDocument具有preserveWhitespace属性,最初设置为False。如果您在True之前将其设置为load,则会使用与原始文件相同的缩进来保存它。

要手动添加缩进,可以创建文本节点并插入它们以在元素之间创建新的行和空格,如下所示:

Set txt = doc.createTextNode(vbCrLf & "  ")
Call node.parentNode.insertBefore(txt, node)

答案 2 :(得分:2)

您可以查看this other question on SO以及答案的C ++代码。但是工作太多了。你说你只是存储一个配置文件。所以使用XSLT转换:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

请记住输出到ADODB.Stream,而不是DOM。如果输出到DOM,则将忽略XSLT序列化程序。

答案 3 :(得分:1)

这是一个较短的缩进实用程序函数,它对DOM对象和字符串起作用作为输入并输出格式化字符串。文件处理(utf-8)不在其范围内。不使用ADODB流,在项目引用中不需要MSXML。

Public Function FormatXmlIndent(vDomOrString As Variant, sResult As String) As Boolean
    Dim oWriter         As Object ' MSXML2.MXXMLWriter

    On Error GoTo QH
    Set oWriter = CreateObject("MSXML2.MXXMLWriter")
    oWriter.omitXMLDeclaration = True
    oWriter.indent = True
    With CreateObject("MSXML2.SAXXMLReader")
        Set .contentHandler = oWriter
        '--- keep CDATA elements
        .putProperty "http://xml.org/sax/properties/lexical-handler", oWriter 
        .parse vDomOrString
    End With
    sResult = oWriter.output
    '--- success
    FormatXmlIndent = True
    Exit Function
QH:
End Function

可以像这样使用

    sXml = ReadTextFile("doc.xml")
    FormatXmlIndent sXml, sXml

...所以如果有任何失败(无效的XML等),sXml仍然保留原始未格式化的输入。