【问题标题】:Having trouble figuring out how to change XML node value generated by PowerShell script无法弄清楚如何更改 PowerShell 脚本生成的 XML 节点值
【发布时间】:2020-04-17 00:41:13
【问题描述】:

我已经涉足 PowerShell 几年了,但我从未处理过 XML,而且我很难找到解决我遇到的问题的方法。我已经阅读了各种论坛上的无数主题,我想我承认我对自己想要完成的工作以及其他人在其他主题中解释的内容还不够了解。

我正在编写其他人编写的 PowerShell 脚本,该脚本主要捕获表数据并将其导出到 XML 文件。正在导出的表数据在其当前状态下是可用的,但是对于某些不是从表中派生的值,我需要找到一种简单的方法来更改 XML 节点的名称。

我的 PS 脚本示例是这样的:

$StartDate = [Management.ManagementDateTimeConverter]::ToDateTime($SYSINFO.LastBootUpTime)
$StartDate = "{0:G}" -F $StartDate
$EndDate = "{0:G}" -F (Get-Date)
$UPTIME = New-TimeSpan -Start $StartDate -End $EndDate
# Format Uptime for "DD:HH:MM:SS.MMMM"
$DispTime = "{0:G}" -F $UPTIME
# Remove .MMMM (Milliseconds)
$DispTime = $DispTime.Split('.')[0]
$DispTime = "$DispTime"

$DispTime | ConvertTo-XML -As String | Out-File -LiteralPath (C:\Scripts\ + "Uptime_Status.xml")

我的 XML 输出最终看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<Objects>
  <Object Type="System.String">0:06:56:39</Object>
</Objects>

我需要做的是将&lt;Object Type="System.String"&gt; 标签更改为其他内容,例如&lt;UPTIME&gt;0:06:56:39&lt;/UPTIME&gt;,或者甚至可能是&lt;Object Type="System.String" Name="Uptime"&gt;0:06:56:39&lt;/Object&gt;

目标是将节点的名称与其他 XML 标记区分开来,当我使用非表数据时,这些标记会与此相同。我还看到需要重复执行此操作的可能性,因此想知道是否可能还有一个选项,即在整个 XML 文件中自动使用 PS 变量的值作为 XML 节点名称。因此,例如,如果我正在处理 20 条数据,并且我可能将要捕获到 XML 中的值之一的数据标记为$DispTime,也许我还可以拥有另一个变量,例如$DispTime_NodeName = "Uptime" ,然后生成的 XML 可能只是:&lt;Uptime&gt;0:06:56:39&lt;/Uptime&gt;。所以基本上 PS 脚本必须找到包含“_NodeName”的匹配变量名称,然后使用该值作为 XML 节点名称。我疯了吗?这是不可能的吗?我是不是想多了?

非常感谢任何愿意提供帮助的人......如果我能得到任何可靠的帮助,我将不胜感激。请记住,我还是个新手 :) 哈哈

【问题讨论】:

    标签: xml powershell nodes


    【解决方案1】:

    对于您问题中的简单示例,您可以从头开始创建自己的 XML 文档:

    $xmlDoc = [xml]::new()
    
    # Add declaration
    [void]$xmlDoc.AppendChild($xmlDoc.CreateXmlDeclaration('1.0', 'utf-8', $null))
    
    # Add <root> node to document
    $root = $xmlDoc.AppendChild($xmlDoc.CreateElement('root'))
    
    # Add <uptime> node to <root>
    $uptime = $root.AppendChild($xmlDoc.CreateElement('uptime'))
    
    # Set inner text value on <uptime> node
    $uptime.InnerText = $DispTime
    
    # Save document
    $xmlDoc.Save((Join-Path C:\Scripts "Uptime_Status.xml"))
    

    如果您想要一种更好的方式来创作 XML 文档,PowerShell Gallery 中的 Xml module 可能会成功:

    安装方式:

    Install-Module Xml
    

    然后:

    Import-Module Xml
    
    $doc = New-XDocument root -Version 1.0 -Encoding utf-8 {
        New-XElement uptime {
          $DispTime
        }
    }
    
    $doc.Save((Join-Path C:\Scripts "Uptime_Status.xml"))
    

    【讨论】:

    • 嗨,马蒂亚斯!非常感谢你的帮助!所以我只是尝试了您提供的第一个建议,但不幸的是我最终遇到了以下错误,我不确定如何解决:
    • 使用“1”参数调用“AppendChild”的异常:“该文档已经有一个‘DocumentElement’节点。”在 C:\Scripts\health_monitoring\xml_test_1.ps1:51 char:1 + $uptime = $xmlDoc.AppendChild($xmlDoc.CreateElement('uptime')) + ~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException
    • 在此对象上找不到属性“InnerText”。验证该属性是否存在并且可以设置。在 C:\Scripts\health_monitoring\xml_test_1.ps1:54 char:1 + $uptime.InnerText = $DispTime + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : PropertyAssignmentException
    • @Andrew 我的回答有错字,现在修正了:)
    • 第二个建议的唯一问题是该脚本将在大量现有服务器上使用,因此在这种情况下安装 XML 模块可能不切实际。我正在使用的代码将被自动推送到这些服务器上的运行目录,但是安装模块会很遗憾地给事情带来一些麻烦,但我真的很感谢你的帮助!!!!!!!!!!!! !!!!!!!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 2014-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    相关资源
    最近更新 更多