如何将日志数据附加到xml文件中?

时间:2012-03-16 07:59:12

标签: xml powershell powershell-v2.0

我在共享文件夹中有一个日志文件。 (最初它只有根元素。)。

每当用户执行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属性。

但我每次都无法追加内容。

如何实现它?

1 个答案:

答案 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对象需要大量空间。

<强>替代

  1. 使用文本文件。只有新数据直接写在最后(打开文件,将写入位置移动到结束和写入)。这表示文件大小没有降级,具有兆字节内容的文件可以添加更多数据,就像新千字节的文件一样快。另外,搜索文件的工具(例如PowerShell的Select-String可以逐步处理文件 - 再次不需要读取整个文件)。

  2. 这是一种破解:使用DTD和XML实体。 LogFile.xml包含一个DTD,用于定义引用LogFileContent.xml-data的外部实体。 <VirtualMachines>中的LogFile.xml节点然后使用该实体导入LogFileContent.xml-data作为其子节点。这意味着LogFileContent.xml-data不需要是有效文档(不需要其根元素)。 但是它确实意味着处理LogFile.xml的任何工具都需要处理该DTD(例如.NET,因此PowerShell,XML支持默认禁用外部实体)。