将XML文档合并到空XML节点中?

时间:2015-06-12 16:57:41

标签: c# xml powershell

编辑:这与链接的发布不完全相同。我遇到的主要问题是将子节点附加到空XML节点。直接选择节点时,它将返回System.String类型,该类型没有AppendChild方法。解决方法是选择所有子节点,然后根据Dan的建议按名称对其进行过滤。

$emptyNode= $root.ChildNodes | ? { $_.name -eq "customers" }

我主要使用的是powershell,但在我正在使用的很多代码下面使用的是.NET System对象。我想要做的事情可能更好地通过一个例子来解释。假设我有三个XML文档:

<!-- XML File A -->
<customer>
    <name>ACME Co</name>
    <users>
        <user>
            <name>Alex</name>
            <age>20</age>
        </user>
        <user>
            <name>Aaron</name>
            <age>21</age>
        </user>
        <user>
            <name>Allison</name>
            <age>22</age>
        </user>
    </users>
</customer>

<!-- XML File B -->
<customer>
    <name>Big Co</name>
    <users>
        <user>
            <name>Bob</name>
            <age>30</age>
        </user>
        <user>
            <name>Barry</name>
            <age>31</age>
        </user>
        <user>
            <name>Bill</name>
            <age>32</age>
        </user>
    </users>
</customer>

<!-- XML File C -->
<customer>
    <name>Cool Co</name>
    <users>
        <user>
            <name>Carl</name>
            <age>40</age>
        </user>
        <user>
            <name>Craig</name>
            <age>41</age>
        </user>
        <user>
            <name>Chris</name>
            <age>42</age>
        </user>
    </users>
</customer>

我有一个“根”文档,如下所示:

<?xml version='1.0' encoding='utf-8' ?>
<customers>
</customers>

我想在根文档下合并三个A,B和C文档,这样我的最终产品将是:

<?xml version='1.0' encoding='utf-8' ?>
<customers>
    <!-- XML File A -->
    <customer>
        <name>ACME</name>
        <users>
            <user>
                <name>Alex</name>
                <age>20</age>
            </user>
            <user>
                <name>Aaron</name>
                <age>21</age>
            </user>
            <user>
                <name>Allison</name>
                <age>22</age>
            </user>
        </users>
    </customer>

    <!-- XML File B -->
    <customer>
        <name>Big Co</name>
        <users>
            <user>
                <name>Bob</name>
                <age>30</age>
            </user>
            <user>
                <name>Barry</name>
                <age>31</age>
            </user>
            <user>
                <name>Bill</name>
                <age>32</age>
            </user>
        </users>
    </customer>

    <!-- XML File C -->
    <customer>
        <name>Cool Co</name>
        <users>
            <user>
                <name>Carl</name>
                <age>40</age>
            </user>
            <user>
                <name>Craig</name>
                <age>41</age>
            </user>
            <user>
                <name>Chris</name>
                <age>42</age>
            </user>
        </users>
    </customer>
</customers>

我一直在关注AppendChild和ImportNode但我一直遇到各种错误。有一件事,就是在我的根文档中,单个空节点customers被列为一种System.String而不是XmlNode,所以我不能追加任何子节点。请参阅此Powershell代码段:

$doc = New-Object System.Xml.XmlDocument
$doc.LoadXml("<?xml version='1.0' encoding='utf-8' ?><customers></customers>")
$doc.customers.GetType()

IsPublic IsSerial Name    BaseType
-------- -------- ----    --------
True     True     String  System.Object

这甚至不重要,因为如果我尝试导入节点,我会收到错误Cannot import nodes of type 'Document'.

$docA = New-Object System.Xml.XmlDocument
$docA.LoadXml("<customer><name>ACME</name><users><user><name>Alex</name><age>20</age></user><user><name>Aaron</name><age>21</age></user><user><name>Allison</name><age>22</age></user></users></customer>")
$docAImported = $doc.ImportNode($docA, $true)

Exception calling "ImportNode" with "2" argument(s): "Cannot import nodes of type 'Document'."
At line:1 char:32
+ $docAImported = $doc.ImportNode <<<< ($docA, $true)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

非常感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:3)

如果您需要使用XML树中的节点,我建议您通过SelectSingleNode()SelectNodes()XPath expression选择节点:

[xml]$doc = "<?xml version='1.0' encoding='utf-8' ?><customers></customers>"
$root = $doc.SelectSingleNode('/customers')

然后您可以importappend来自其他XML文件的节点,如下所示:

Get-ChildItem '*.xml' | % {
  [xml]$xml = Get-Content $_.FullName
  $node = $xml.SelectSingleNode('/customer')
  $importedNode = $doc.ImportNode($node, $true)
  $root.AppendChild($importedNode)
}

$doc.Save('C:\path\to\customers.xml')

答案 1 :(得分:2)

首先通过执行以下操作获取客户节点:

$customersNode = $doc.ChildNodes | ? { $_.name -eq "customers" }

现在,您可以使用文档A,B和C在$ customersNode上调用AppendChild。

然而,要导入文档A,B和C,你几乎是正确的。使用DocumentElement属性,如下所示:

$docAImported = $doc.ImportNode($docA.DocumentElement, $true)