加载包含自定义命名空间

时间:2016-10-14 11:13:55

标签: xml powershell

使用PowerShell脚本动态附加XML标记。 在这种情况下,尝试为NLog添加自定义ElasticSearch目标(来自here)。

$source = '<target name="elastic" xsi:type="BufferingWrapper">  </target>'

使用

$source转换为XML时
[xml]$source

$xml = New-Object -TypeName System.Xml.XmlDocument
$xml.LoadXml($source)

我收到以下错误

  

无法转换价值&#34;&lt; targetname =&#34; elastic&#34;的xsi:type =&#34; BufferingWrapper&#34;&GT; &LT; /靶GT;&#34;输入&#34; System.Xml.XmlDocument&#34;。错误:&#34;&#39; xsi&#39;是一个未声明的前缀。&#34;

有什么建议吗?

几乎,但不完全在那里:

我可以使用ConvertTo-Xml $source -as Document,但结果并未使用<target>标记,它使用<Object>,在这种情况下不起作用。

<?xml version="1.0" encoding="utf-8"?>
<Objects>
  <Object Type="System.String">&lt;target name="elastic" xsi:type="BufferingWrapper"
<Objects>

1 个答案:

答案 0 :(得分:2)

您可以按this answer

中所述加载XML片段
$source = '<target name="elastic" xsi:type="BufferingWrapper"></target>'
$sreader = New-Object IO.StringReader $source
$xreader = New-Object Xml.XmlTextReader $sreader
$xreader.Namespaces = $false
$fragment = New-Object Xml.XmlDocument
$fragment.Load($xreader)

但是,假设您希望在某个时刻将该片段导入另一个XML数据结构,这样做可能会导致其他问题(例如参见this question)。

要解决此问题,请在XML片段中添加具有正确名称空间定义的虚拟根节点:

$source = '<target name="elastic" xsi:type="BufferingWrapper">  </target>'
[xml]$fragment = "<dummy xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>$source</dummy>"

通过这种方式,您可以将节点导入到另一个这样的XML文档中(前提是其他XML文件也包含正确的命名空间定义):

[xml]$xml = Get-Content 'C:\path\to\master.xml'

$nsm = New-Object Xml.XmlNamespaceManager $xml.NameTable
$nsm.AddNamespace('xsi', $xml.NamespaceURI)

$node = $xml.ImportNode($fragment.DocumentElement.target, $true)

$targets = $xml.SelectSingleNode('//targets', $nsm)
$targets.AppendChild($node) | Out-Null