Найти / заменить в XML-файле парами имя / значение

Я пытаюсь написать сценарий оболочки, который будет принимать в качестве входных данных набор пар имя / значение и файл XML.

Цель состоит в том, чтобы найти в файле XML строку "имя" из файла пар имя / значение (разграниченную тегами) и заменить строку "значение", определенную на том же уровне файла XML (разграниченную тегами).

например

Файл пар имя / значение

trousers=blue
hat=red
shoes=brown

Входной XML-файл

<application>
    <Pairs>
        <Pair>
            <name>trousers</name>
            <value>black</value>
        </Pair>
        <IrritatingExtraLayer>
            <Pair>
                <name>hat</name>
                <value>green</value>
            </Pair>
        </IrritatingExtraLayer>
        <Pair>
            <name>shirt</name>
            <value>orange</value>
        </Pair>
    </Pairs>
</application>

Ожидаемый выходной файл

<application>
    <Pairs>
        <Pair>
            <name>trousers</name>
            <value>blue</value>
        </Pair>
        <IrritatingExtraLayer>
            <Pair>
                <name>hat</name>
                <value>red</value>
            </Pair>
        </IrritatingExtraLayer>
        <Pair>
            <name>shirt</name>
            <value>orange</value>
        </Pair>
    </Pairs>
</application>

Я уже создал скрипт, который может сделать это с помощью xmlstarlet, однако он очень медленный (файлы, с которыми я работаю, имеют длину в тысячи строк). Основной фрагмент кода (без предварительной и последующей обработки) из моего скрипта:

for line in ${namevaluepairs}; do
                name=$(echo ${line} | cut -d'=' -f1)
                value=$(echo ${line} | cut -d'=' -f2)

                outputxml=$(echo ${outputxml} | xmlstarlet ed -u "//Pair/[name='${name}']/value" -v "${value}" )
done

Что я могу сделать, чтобы улучшить это?

1 ответ

Я обычно использую xsh для подобных задач. Мне было бы интересно, насколько быстро следующее по сравнению с xmlstarlet.

perl { 
    open $FH, '<', 'namevalues' or die $!;
    while (<$FH>) {
        chomp;
        ($n, $v) = split /=/;
        $h->{$n} = $v;
    }
} ;
open 1.xml ;
for //name {
    $v = xsh:lookup('h', text()) ;
    if $v set ../value $v ;
}
save :b ;

Хитрость заключается в том, чтобы сохранить пары имя-значение в хэше (карта, словарь), затем обработать все имена и извлечь соответствующие значения из хеша.

Другие вопросы по тегам