我在共享文件夹中有一个日志文件。 (最初它只有根元素。)。
每当用户执行powershell脚本时,必须将日志数据附加到XML。
<VM>
<VMName>Fresh_R2VM</VMName>
<AccessedBy>David</AccessedBy>
<AccessedDate>Today's date</AccessedDate>
<AccessedTime>current Time</AccessedTime>
</VM>
我的XML日志文件最初会像这样
<VirtualMachines version="1.0">
</virtualMachines>
第一个用户(david)执行脚本后,我的日志文件应该是这样的。
<VirtualMachines version="1.0">
<VM>
<VMName>Fresh_R2VM</VMName>
<AccessedBy>David</AccessedBy>
<AccessedDate>Today's date</AccessedDate>
<AccessedTime>current Time</AccessedTime>
</VM>
</virtualMachines>
如果david第二次执行,则应追加另一个条目。
<VirtualMachines version="1.0">
<VM>
<VMName>Fresh_R2VM</VMName>
<AccessedBy>David</AccessedBy>
<AccessedDate>Today's date</AccessedDate>
<AccessedTime>current Time</AccessedTime>
</VM>
<VM>
<VMName>Fresh_R2VM</VMName>
<AccessedBy>David</AccessedBy>
<AccessedDate>Today's date</AccessedDate>
<AccessedTime>current Time</AccessedTime>
</VM>
</virtualMachines>
我试图使用模板xml文件实现此目的,然后将模板克隆到日志文件并更新内容。但它留下了一个空标签。我设法删除使用removechild属性。
但我每次都无法追加内容。
如何实现它?
答案 0 :(得分:2)
将XML用于日志文件是一种糟糕的方法,特别是如果日志文件变大,成本会很高;更多信息如下。
解决方案:
$file = Resolve-Path 'logfile.xml'
$output = [xml](Get-Content $file)
$vmNode = $output.DocumentElement
$newNode = [xml]@"
<VM>
<VMName>Fresh_R2VM</VMName>
<AccessedBy>David</AccessedBy>
<AccessedDate>$([DateTime]::Today)</AccessedDate>
<AccessedTime>$([DateTime]::Now.ToString('HH:mm:ss'))</AccessedTime>
</VM>
"@
# Need to move the VM node from document newNode to the output document
$newNode = $output.ImportNode($newNode.DocumentElement, $true)
$vmNode.appendChild($newNode) | out-null
$output.Save($file)
性能:每次添加新节点时,它都会加载并完全解析现有文档,然后附加一个节点,然后保存整个文档。每个追加将比前一个更长。有几千个节点,这可能是重要的,有几十万肯定会。解析后的XML开始成为主要的内存开销 - 代表非平凡XML文档的XmlDocument
对象需要大量空间。
<强>替代强>
使用文本文件。只有新数据直接写在最后(打开文件,将写入位置移动到结束和写入)。这表示文件大小没有降级,具有兆字节内容的文件可以添加更多数据,就像新千字节的文件一样快。另外,搜索文件的工具(例如PowerShell的Select-String
可以逐步处理文件 - 再次不需要读取整个文件)。
这是一种破解:使用DTD和XML实体。 LogFile.xml
包含一个DTD,用于定义引用LogFileContent.xml-data
的外部实体。 <VirtualMachines>
中的LogFile.xml
节点然后使用该实体导入LogFileContent.xml-data
作为其子节点。这意味着LogFileContent.xml-data
不需要是有效文档(不需要其根元素)。 但是它确实意味着处理LogFile.xml
的任何工具都需要处理该DTD(例如.NET,因此PowerShell,XML支持默认禁用外部实体)。