在 XML 值 null 中添加元素

问题描述 投票:0回答:2

我正在尝试在 XML 文件中添加新元素。下面是 XML 文件。我的目标是添加几个新的 Svc,其属性为 Name、Displayname、Activ、CommadState、Status。

由于我的 Svc 元素没有 ID 或其他东西,我无法添加然后编辑我必须直接添加正确的值

我已经尝试过这样的操作,但它说我正在尝试调用空值表达式。

$drive = "E:"

$filePath = Get-Content $drive\Alarm\Services\ProgWatch\ProgWatchServices.xml

$doc = New-Object System.Xml.XmlDocument
$doc.Load($filePath)
$child = $doc.CreateElement("Svc")
$doc.DocumentElement.AppendChild($child)
<?xml version="1.0" encoding="utf-8"?> 
<ArrayOfSvc xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">   
  <Svc>
    <Name>Respus</Name>
    <Displayname>Respus</Displayname>
    <Activ>true</Activ>
    <CommadState>NoCommand</CommadState>
    <Status>Running</Status>   </Svc>   <Svc>
    <Name>AlarmUS</Name>
    <Displayname>AlarmUS</Displayname>
    <Activ>true</Activ>
    <CommadState>NoCommand</CommadState>
    <Status>Running</Status>   </Svc>   <Svc>
    <Name>asProgWatchGuard</Name>
    <Displayname>Prog Watch Guardian</Displayname>
    <Activ>true</Activ>
    <CommadState>NoCommand</CommadState>
    <Status>Running</Status>   
  </Svc>   
  <Svc>
    <Name>asBackup</Name>
    <Displayname>Data Backup</Displayname>
    <Activ>true</Activ>
    <CommadState>NoCommand</CommadState>
    <Status>Running</Status>   
  </Svc> 
</ArrayOfSvc>
xml powershell element
2个回答
0
投票

这看起来像 PowerShell。这是使用 Xml Linq 网络库的代码

using assembly System.Xml.Linq

$filename = "c:\temp\test.xml"
$doc = [System.Xml.Linq.XDocument]::Load($filename)
$arrayOfSvc = $doc.Root

$child = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get('Svc'))
$arrayOfSvc.Add($child)
$doc

0
投票

tl;博士

  • 要立即修复,请将

    .Load()
    更改为
    .LoadXml()

  • 一个健壮且更高效的方法是将文件路径直接传递给

    .Load()
    方法:

$drive = "E:"

# Note: Be sure to use a *full path*.
$filePath = "$drive\Alarm\Services\ProgWatch\ProgWatchServices.xml"

$doc = New-Object System.Xml.XmlDocument
$doc.Load($filePath)
$child = $doc.CreateElement("Svc") # An empty new element - see also below.
$doc.DocumentElement.AppendChild($child)

在插入之前填充新的 XML 元素:

上面仅创建了一个 empty

<Svc>
元素。
填充新元素,您有两个选择:

  • 使用方法迭代创建所需的结构;例如:

    $child = $doc.CreateElement('Svc')
    $grandChild1 = $doc.CreateElement('Name')
    $grandChild1.InnerText = 'newName'
    $grandChild2 = $doc.CreateElement('DisplayName')
    $grandChild2.InnerText = 'newDisplayName'
    # ...
    $null = $child.AppendChild($grandChild1)
    $null = $child.AppendChild($grandChild2)
    # ...
    # Finally, insert the completed new child element into the document
    $null = $doc.DocumentElement.AppendChild($child)
    
  • 更方便的是,使用通过

    XmlDocumentFragment
    获取的
    .CreateDocumentFragment()
    实例,从表示所需结构的 XML string 构造新元素;例如:

    $child = $doc.CreateDocumentFragment()
    $child.InnerXml = '
      <Svc>
        <Name>{0}</Name>
        <Displayname>{1}</Displayname>
        <Activ>{2}</Activ>
        <CommadState>{3}</CommadState>
        <Status>{4}</Status>
      </Svc>
     ' -f 'newName', 'newDisplayName', 'false', 'NoCommand', 'Suspended'
    # Insert the completed new child element into the document
    $null = $doc.DocumentElement.AppendChild($child)
    

从文件重新加载XML的后台信息:

您的

$filePath
变量 - 尽管其名称 - 包含 XML 文本,因为您在文件路径中使用了
Get-Content

因此,立即修复方法是使用

.LoadXml()
而不是
.Load()
类的
System.Xml.XmlDocument
方法(您可以在 PowerShell 中将其称为
[xml]
)。

但是,最好避免这种从文件加载 XML 的两步方法,原因如下:

  • 效率:直接使用

    .Load()
    方法与文件路径只需要一次调用。

    • 注意:请务必始终将完整路径传递给 .NET 方法,因为 .NET 的工作目录通常与 PowerShell 的不同。
  • 字符编码:

    • .Load()
      方法在读取时默认为UTF-8并且特别尊重XML声明中的
      encoding
      属性
      (例如,
      <?xml version="1.0" encoding="ISO-8859-1"?>
      )(如果字符编码是不同的) .

    • 相比之下,

      Get-Content
      不会这样做(它从不解释文件的内容),并且在Windows PowerShell中默认为 ANSI 编码,即系统的活动旧版 ANSI 代码页隐含的编码(相比之下,PowerShell(核心)7+现在值得称赞的是,所有 cmdlet 都默认为(无 BOM)UTF-8。

    • 换句话说:
    • Get-Content可能会误解您的 XML 文件。

      
      
      

      • [xml]

        型加速器结合使用,

        Get-Content
        诱人
        ,但不稳健。如果您愿意假设 Get-Content
        不会
        误解 XML 文件,或者您知道实际编码并通过 -Encoding 指定它,则可以使用以下
        shortcut
        ;请注意使用 -Raw 来读取整个文件
        作为一个整体
        ,这比默认情况下执行的逐行读取快得多) Get-Content
        
        

        稳健
      • 方法
      • 简明表述(如顶部所示)是: # Convenient, but NOT ROBUST # May need an -Encoding argument. $doc = [xml] (Get-Content -Raw $filePath)

        
        
© www.soinside.com 2019 - 2024. All rights reserved.