带CDATA的VBScript XML缩进

带CDATA的VBScript XML缩进,xml,vbscript,indentation,Xml,Vbscript,Indentation,我想从VBScript生成一个XML文件。我找到了Microsoft.XMLDOM,但这个类似乎不知道如何缩进我的输出文件。我试图使用MSXML2来增强我的xml,但当我使用它时,我的CDATA部分消失了 VBScript: set xml = CreateObject("Microsoft.XMLDOM") set encoding = xml.createProcessingInstruction("xml", "version='1.0' encoding='ISO-8859-1'") x

我想从VBScript生成一个XML文件。我找到了
Microsoft.XMLDOM
,但这个类似乎不知道如何缩进我的输出文件。我试图使用MSXML2来增强我的xml,但当我使用它时,我的CDATA部分消失了

VBScript:

set xml = CreateObject("Microsoft.XMLDOM")
set encoding = xml.createProcessingInstruction("xml", "version='1.0' encoding='ISO-8859-1'")
xml.insertBefore encoding, xml.childNodes.Item(0)
set foo = xml.createElement("foo")
foo.setAttribute "foobar", "42"

set bar = xml.createElement("bar")
set cdata = xml.createCDATASection("Hello World!")
bar.appendChild cdata
foo.appendChild bar
xml.appendChild(foo)

' XML okay but ugly because no indentation
xml.save("a.xml")

' XML pretty but the 'cdata' sections vanished...
xmlSave xml, "b.xml"

function xmlSave(xml, filename)
    set rdr = CreateObject("MSXML2.SAXXMLReader")
    set wrt = CreateObject("MSXML2.MXXMLWriter")
    Set oStream = CreateObject("ADODB.STREAM")
    oStream.Open
    oStream.Charset = "ISO-8859-1"

    wrt.indent = True
    wrt.encoding = "ISO-8859-1"
    wrt.output = oStream
    Set rdr.contentHandler = wrt
    Set rdr.errorHandler = wrt

    rdr.Parse xml
    wrt.flush

    oStream.SaveToFile filename, 2
end function
输出:

$ cscript //nologo test.vbs && cat a.xml && echo -e "------" && cat b.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<foo foobar="42"><bar><![CDATA[Hello World!]]></bar></foo>
------
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<foo foobar="42">
        <bar>Hello World!</bar>
</foo>
$cscript//nologo test.vbs&&cat a.xml&&echo-e“---”&&cat b.xml
------
你好,世界!

如何在不丢失CDATA部分的情况下,使用XMLDOM轻松获得一个良好的缩进XML

我发现了一些有用的东西

Function ParseAndSave(filePath, xmlDoc)
    set xmlWriter = CreateObject("MSXML2.MXXMLWriter")
    set xmlReader = CreateObject("MSXML2.SAXXMLReader")
    Set xmlStream = CreateObject("ADODB.STREAM")
    xmlStream.Open
    xmlStream.Charset = "ISO-8859-1"

    xmlWriter.output = xmlStream
    xmlWriter.indent = True
    xmlWriter.standalone = True
    xmlWriter.encoding = "ISO-8859-1"

    Set xmlReader.contentHandler = xmlWriter
    Set xmlReader.DTDHandler = xmlWriter
    Set xmlReader.errorHandler = xmlWriter
    xmlReader.putProperty "http://xml.org/sax/properties/lexical-handler", xmlWriter
    xmlReader.putProperty "http://xml.org/sax/properties/declaration-handler", xmlWriter

    xmlReader.parse xmlDoc
    xmlWriter.flush

    xmlStream.SaveToFile filePath, 2

    xmlStream.Close
    Set xmlStream = Nothing
    Set xmlWriter = Nothing
    Set xmlReader = Nothing
End Function 

我在您的代码中看到的第一个误解是假定
是一条处理指令。事实并非如此。这是XML声明。您不能使用
createProcessingInstruction()
生成它。尝试将导致输出文档损坏

下一个误解是XML必须看起来整洁。或者你需要CDATA来做任何事情

这两点可能有点争议,但一般来说,外观整洁的XML和CDATA都不能满足任何技术目的。如果你的强迫症允许,克服它们

第三个误解是“缩进”不是只包含空格的文本节点。XML保留您的数据,文本节点(空白或非空白)是数据。如果不添加任何只包含换行符和空格/制表符的文本节点,则输出中将不会有任何文本节点

简而言之:如果想要缩进节点,必须手动添加缩进。这个过程通常被称为“漂亮的印刷”

你可以用递归函数打印一个文档,就像这样(得到这个“正确”的函数比你想象的要复杂,我不能保证输出就是你想要的):

”公共函数,将DOMDocument传递给它。就地修改该文档。
子契约文档(doc,indentStr)
IndentNode doc.DocumentElement,左(indentStr,1),Len(indentStr),0
端接头
' --------------------------------------------------------------------------
'帮助器函数,不直接调用。。。
子缩进节点(节点、缩进字符、每级别、级别)
模糊父项、子项、文档
如果node.NodeType=9,则
IndentNode node.DocumentElement,indentChar,perLevel,level
ElseIf CanIndent(节点)然后
缩进删除节点
设置文档=node.OwnerDocument
如果节点不是doc.DocumentElement,则
设置parent=node.ParentNode
如果节点是parent.FirstChild或CanIndent(node.PreviousSibling),则
parent.InsertBefore doc.createTextNode(vbLf&String(level*perLevel,indentChar)),节点
如果结束
如果节点是parent.LastChild,则
parent.InsertBefore doc.createTextNode(vbLf&String((级别-1)*perLevel,indentChar)),无任何内容
如果结束
如果结束
如果node.ChildNodes.Length>0,则
对于node.ChildNodes中的每个子节点
IndentNode子节点、indentChar、每级别、级别+1
下一个
如果结束
如果结束
端接头
函数CanIndent(节点)
如果节点为空,则
CanIndent=False
其他的
CanIndent=node.NodeType=1或node.NodeType=8
如果结束
端函数
子缩进移除(节点)
昏昏欲睡的孩子,我
对于i=node.ChildNodes.Length到1步-1
Set child=node.ChildNodes(i-1)
如果child.NodeType=3且Trim(Replace(Replace(child.Text,vbCr,“”,vbLf,“”))为“”,则
node.RemoveChild子节点
如果结束
设置child=Nothing
下一个
端接头
用法

Set doc=CreateObject(“MSXML2.DOMDocument”)
'加载带有预定义输出编码的框架XML文档
doc.LoadXML“”
' ... 现在在这里创建所有类型的节点。。。
'用两个空格缩进文档并保存
缩进文档文件“
doc.Save“foo.xml”

一般情况下:如果您想使用ISO-859-1来创建任何新文件,请仔细考虑。UTF-8是当今的发展方向,您不应该再为任何新的内容使用传统的文件编码。尤其是在XML中,因为所有XML解析器都理解UTF-8。

哇,有人真的否决了这一点。有趣的选择。欧欧欧