【问题标题】:Merge XML documents into empty XML node?将 XML 文档合并到空的 XML 节点中?
【发布时间】:2015-08-28 18:46:30
【问题描述】:

编辑:这与链接的帖子不太一样。我遇到的主要问题是将子节点附加到一个空的 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 sn-p:

$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

任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: xml powershell


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 谢谢,$doc.ChildNodes | ? { $_.name -eq "customers" } 部分正是我所需要的。我给出的示例与我正在使用的 XML 不是一对一的,但足以解决问题。
    【解决方案2】:

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

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

    然后您可以像这样从其他 XML 文件中 importappend 节点:

    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')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多