如果节点不存在,augeas 添加 xml 部分

augeas adding xml section to if node does not exist

<root>
<node name="Client">
    <node name="Attributes">
        <info>
            <hash>
                <entry><key>colour</key><value type="string">blue</value></entry>
            </hash>
        </info>
    </node>
</node>
<node name="Network">
    <node name="A">
        <info>
            <hash>
                <entry><key>NetName</key><value type="string">bnx1</value></entry>
                <entry><key>transport</key><value type="string">internet</value></entry>
                <entry><key>ipAddr</key><value type="string">125.125.125.142</value></entry>
                <entry><key>portNo</key><value type="string">1234</value></entry>
                <entry><key>protocolType</key><value type="string">tcp</value></entry>
            </hash>
        </info>
    </node>
    <node name="B">
        <info>
            <hash>
                <entry><key>transport</key><value type="string">internet</value></entry>
                <entry><key>ipAddr</key><value type="string">125.125.125.142</value></entry>
                <entry><key>portNo</key><value type="string">1234</value></entry>
                <entry><key>protocolType</key><value type="string">tcp</value></entry>
            </hash>
        </info>
    </node>
</node>
</root>

我想在名称=B 的节点中创建一个条目,该条目具有键 NetName 和值 bnx2,如果它不存在的话。 我正在将 augeas 与木偶一起使用。

以下是您可以使用 augtool 执行的操作:

augtool> defvar hash /files/39143450.xml/root/node[#attribute/name="Network"]/node[#attribute/name="B"]/info/hash
augtool> defnode entry $hash/entry[key/#text="NetName"]
augtool> set $entry/key/#text "NetName"
augtool> set $entry/value/#attribute/type "string"
augtool> set $entry/value/#text "bnx2"
augtool> save

将其转换为 Puppet 定义的类型:

define entry (
  $value,
  $file,
  $ensure = 'present',
  $node = 'B',
) {
  case $ensure {
    'present': {
      $changes = [
        "defnode entry entry[key/#text='${name}'] ''",
        "set $entry/key/#text '${name}'",
        "set $entry/value/#attribute/type 'string'",
        "set $entry/value/#text '${value}'",
      ]
    }

    'absent': {
      $changes = "rm entry[key/#text='${name}']"
    }

    default: {
      fail("Unknown value for ensure: ${ensure}")
    }
  }

  augeas { "Set ${title} in ${file}":
    incl    => $file,
    lens    => 'Xml.lns',
    context => "/files${file}/root/node[#attribute/name='Network']/node[#attribute/name='${node}']/info/hash",
    changes => $changes,
  }
}

entry { 'NetName':
  value => 'bnx2',
  file  => '/path/to/39143450.xml',
}

运行人偶:

Notice: Compiled catalog for example.com in environment production in 0.15 seconds
Notice: /Stage[main]/Main/Entry[NetName]/Augeas[Set NetName in /path/to/39143450.xml]/returns: executed successfully
Notice: Applied catalog in 0.09 seconds

嵌套 'node' 使这项任务变得困难。标签 'nodes' 然后 'node' 会更好。 试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication11
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            List<XElement> rootNodes = doc.Element("root").Elements("node").ToList();
            List<XElement> bNodes = rootNodes.Select(x => x.Elements("node").Where(y => (string)y.Attribute("name") == "B")).SelectMany(z => z).ToList();
            foreach (XElement bHash in bNodes.Descendants("hash"))
            {
                Boolean netName = bHash.Descendants("key").Where(x => (string)x == "NetName").Any();
                if (!netName)
                {
                    bHash.Add(new XElement("entry", new object[] {
                        new XElement("key","NetName"),
                        new XElement("value", new object[] {
                            new XAttribute("type","string"),
                            "value"
                        })
                    }));
                }
            }

        }
    }

}