2011-06-19 50 views
3

我正在使用MSXML 3.0和Visual Basic 6來存儲和檢索我的應用程序的配置。當保存生成的DOMDocument到XML文件中的根對象被呈現爲一個很長的一行文字:強制MSXML格式化帶有縮進和換行符的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文件?

回答

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序列化程序將被忽略。

+0

你能介紹一下你把它放到MSXML的地方嗎? –

+0

@MattMcNabb - 將代碼放入XSLT文件(如'pretty.xsl')中,然後運行轉換,可以使用[Microsoft'msxsl.exe'命令行實用程序](http:// www。 microsoft.com/en-us/download/details.aspx?id=21714)或任何其他XSLT處理器。您也可以[使用MSXML API進行轉換](https://msdn.microsoft.com/en-us/library/ms766561(v = vs.85).aspx)。 – Lumi

+0

謝謝;然而輸出沒有像預期的那樣出來,我[開始了一個新問題](http://stackoverflow.com/questions/28133229/xslt-indent-not-working-with-msxml) –

4

對於配置文件這樣的小文件,使用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 
3

也許這個答案對你的具體情況沒有幫助,但總的來說它可能是有用的。它將文檔加載和保存時的情況視爲沒有太多修改。 DomDocumentpreserveWhitespace屬性,它最初設置爲False。如果在load之前將其設置爲True,則它將使用與原始文件相同的縮進進行保存。

要添加縮進手動一個可以創建文本節點,並把它們插入到創建元素之間的新線條和空間,像這樣:

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

這實際上非常有用。我不相信任何提出的xslt變換都可以用於6.0以前版本的msxml:我已經花了很多時間在這個上,儘管我還沒有找到一個記錄的原因爲什麼不這樣做,但我不認爲這個「縮進「標誌在6.0之前被支持 –

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仍持有原非格式化的輸入。