Powershell:使用命名空间向XML文档添加元素

时间:2014-04-24 21:27:21

标签: xml powershell xml-parsing vmware vcloud-director-rest-api

我正在尝试编写一个powershell cmdlet,它使用VMWare的vcloud REST API添加一个NIC(VMWare自己的powerCLI似乎不允许这样做)。为此,我需要使用这个XML:

<?xml version="1.0" encoding="UTF-8"?><vcloud:RasdItemsList
    xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
    xmlns:vcloud="http://www.vmware.com/vcloud/v1.5"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    href="https://vcloud.example.com/api/vApp/vm-89c84bd6-c6f2-4e4c-8a7d-c44a3489e2e4/virtualHardwareSection/networkCards"
    type="application/vnd.vmware.vcloud.rasdItemsList+xml">
    <vcloud:Link
        href="https://vcloud.example.com/api/vApp/vm-89c84bd6-c6f2-4e4c-8a7d-c44a3489e2e4/virtualHardwareSection/networkCards"
        rel="edit"
        type="application/vnd.vmware.vcloud.rasdItemsList+xml"/>
</vcloud:RasdItemsList>

并在最后一个vcloud下面添加以下元素:链接。

    <ovf:Item>
        <rasd:Address></rasd:Address>
        <rasd:AddressOnParent>0</rasd:AddressOnParent>
        <rasd:AutomaticAllocation>false</rasd:AutomaticAllocation>
        <rasd:Connection
            vcloud:ipAddressingMode="none"
            vcloud:primaryNetworkConnection="true">VM Network</rasd:Connection>
        <rasd:Description>E1000 ethernet adapter on "VM Network"</rasd:Description>
        <rasd:ElementName>Network adapter 0</rasd:ElementName>
        <rasd:InstanceID>1</rasd:InstanceID>
        <rasd:ResourceSubType>E1000</rasd:ResourceSubType>
        <rasd:ResourceType>10</rasd:ResourceType>
    </ovf:Item>

现在,我已将原始XML作为$ xmlDoc加入PS,我尝试了以下代码:

$xmlElt = $xmlDoc.CreateElement("ovf:Item")
$xmlSubElt = $xmlDoc.CreateElement("rasd:Address")
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:AddressOnParent")
$xmlSubText = $xmlDoc.CreateTextNode("0")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:AutomaticAllocation")
$xmlSubText = $xmlDoc.CreateTextNode("false")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:Connection")
$xmlSubText = $xmlDoc.CreateTextNode("none")
$xmlSubElt.AppendChild($xmlSubText)
$xmlAtt = $xmlDoc.CreateAttribute("vcloud:primaryNetworkConnection")
$xmlAtt.Value = "True"
$xmlSubElt.Attributes.Append($xmlAtt)
$xmlAtt = $xmlDoc.CreateAttribute("vcloud:ipAddressingMode")
$xmlAtt.Value = "NONE"
$xmlSubElt.Attributes.Append($xmlAtt)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:Description")
$xmlSubText = $xmlDoc.CreateTextNode("Network Adapter 0")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:ElementName")
$xmlSubText = $xmlDoc.CreateTextNode("Network Adapter 0")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:InstanceID")
$xmlSubText = $xmlDoc.CreateTextNode("0")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:ResourceSubType")
$xmlSubText = $xmlDoc.CreateTextNode("E1000")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:ResourceType")
$xmlSubText = $xmlDoc.CreateTextNode("10")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlDoc.LastChild.AppendChild($xmlElt);

以下是这个创建的XML的相关位:

<Item>
  <Address />
  <AddressOnParent>0</AddressOnParent>
  <AutomaticAllocation>false</AutomaticAllocation>
  <Connection primaryNetworkConnection="True" ipAddressingMode="NONE">none</Connection>
  <Description>Network Adapter 0</Description>
  <ElementName>Network Adapter 0</ElementName>
  <InstanceID>0</InstanceID>
  <ResourceSubType>E1000</ResourceSubType>
  <ResourceType>10</ResourceType>
</Item>

正如您所看到的,它主要起作用,但遗憾的是它似乎正在删除XML Namespace前缀。它可能仍然有效,但我真的很想匹配格式。我是XML和Powershell交互的新手,所以我的问题是:

  1. 如何输出命名空间?
  2. 是否有一种更简单的方法可以手动创建这样的元素,我只是愚蠢地忽略了?

2 个答案:

答案 0 :(得分:2)

解决了我自己的问题。我需要从&#34; rasdItemsList&#34;加载名称空间。 xpath进入System.Xml.XmlNamespaceManager,然后在创建元素时查找每个URI的URI。

$nsm = New-Object System.Xml.XmlNamespaceManager($xmldoc.nametable)
$nsm.addnamespace("xsi", $xmldoc.rasdItemsList.GetNamespaceOfPrefix("xsi"))
$nsm.addnamespace("rasd", $xmldoc.rasdItemsList.GetNamespaceOfPrefix("rasd"))
$nsm.addnamespace("vcloud", $xmldoc.rasdItemsList.GetNamespaceOfPrefix("vcloud"))

$xmlElt = $xmlDoc.CreateElement("vcloud:Item", $nsm.LookupNamespace("vcloud"))
$xmlSubElt = $xmlDoc.CreateElement("rasd:Address", $nsm.LookupNamespace("rasd"))
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:AddressOnParent", $nsm.LookupNamespace("rasd"))
$xmlSubText = $xmlDoc.CreateTextNode("0")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:AutomaticAllocation", $nsm.LookupNamespace("rasd"))
$xmlSubText = $xmlDoc.CreateTextNode("false")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:Connection", $nsm.LookupNamespace("rasd"))
$xmlSubText = $xmlDoc.CreateTextNode("none")
$xmlSubElt.AppendChild($xmlSubText)
$xmlAtt = $xmlDoc.CreateAttribute("vcloud:primaryNetworkConnection", $nsm.LookupNamespace("vcloud"))
$xmlAtt.Value = "True"
$xmlSubElt.Attributes.Append($xmlAtt)
$xmlAtt = $xmlDoc.CreateAttribute("vcloud:ipAddressingMode", $nsm.LookupNamespace("vcloud"))
$xmlAtt.Value = "NONE"
$xmlSubElt.Attributes.Append($xmlAtt)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:Description", $nsm.LookupNamespace("rasd"))
$xmlSubText = $xmlDoc.CreateTextNode("Network Adapter 0")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:ElementName", $nsm.LookupNamespace("rasd"))
$xmlSubText = $xmlDoc.CreateTextNode("Network Adapter 0")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:InstanceID", $nsm.LookupNamespace("rasd"))
$xmlSubText = $xmlDoc.CreateTextNode("0")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:ResourceSubType", $nsm.LookupNamespace("rasd"))
$xmlSubText = $xmlDoc.CreateTextNode("E1000")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlSubElt = $xmlDoc.CreateElement("rasd:ResourceType", $nsm.LookupNamespace("rasd"))
$xmlSubText = $xmlDoc.CreateTextNode("10")
$xmlSubElt.AppendChild($xmlSubText)
$xmlElt.AppendChild($xmlSubElt)
$xmlDoc.LastChild.AppendChild($xmlElt);

答案 1 :(得分:0)

为什么不使用PowerCLI?

New-NetworkAdapter -VM $vm -NetworkName "VM Network" -MacAddress  'aa:bb:cc:dd:ee:ff' -WakeOnLan -StartConnected