2015-06-12 3 views
0

EDIT: Это не совсем то же самое, что и опубликованный, который был связан. Основная проблема, с которой я столкнулся, заключалась в добавлении дочерних узлов в пустой узел XML. При непосредственном выборе узла он возвращает тип System.String, который не имеет метода AppendChild. Исправление заключалось в том, чтобы выбрать все дочерние узлы, а затем отфильтровать их по имени, по предложению Дэна ниже.Объединить XML-документы в пустой узел XML?

$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 u NDER корневого документа таким образом мой конечный продукт будет:

<?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

Получить узел клиента первой, выполнив следующие действия:

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

Теперь вы можете позвонить AppendChild на $ customersNode с документом A, B и C.

Однако импортировать документ A, B и C вы почти все правильно. Используйте свойство DocumentElement, как показано ниже:

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

Спасибо, '$ doc.ChildNodes | ? {$ _. name -eq "customers"} 'часть - это то, что мне нужно.Пример, который я дал, был не совсем единым для XML, с которым я работаю, но этого было достаточно, чтобы решить проблему. – romellem

3

Если вам нужно работать с узлами из дерева XML я бы рекомендовал, чтобы выбрать узел (ы) с помощью SelectSingleNode() или SelectNodes() и XPath expression:

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

Тогда вы можете import и append узлы из других ваших файлов 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') 
Смежные вопросы