2015-11-19 4 views
0

Я хотел бы заменить определенные значения (не для всех элементов). Здесь все имеют тот же Background_color, но я не хочу заменять Background_color только для определенного. Как мы можем реализовать? . Это просто пример кода (я бы список имен кожи в файле, для которого я не должен заменить background_color)Заменить конкретные теги в xml в unix

  <Skins> 
      <skin> 
       <att name="Name" value="sknLblG3S3" type="String"/> 
       <att name="WidgetType" value="Label" type="String"/> 
       <att name="Background_color" value="228,221,213" type="RGB"/> 
      <skin> 
      <skin> 
       <att name="Name" value="name" type="String"/> 
       <att name="WidgetType" value="Label" type="String"/> 
       <att name="Background_color" value="228,221,213" type="RGB"/> 
      <skin> 
      <skin> 
       <att name="Name" value="sknLblG3S5" type="String"/> 
       <att name="WidgetType" value="Label" type="String"/> 
       <att name="Background_color" value="228,221,213" type="RGB"/> 
      <skin> 
      <skins> 
+0

Я хотел бы выполнить итерацию по всему XML-файлу. –

+1

Что вы пробовали? – mkHun

+0

Несмотря на то, что я обычно увлекаюсь людьми, которые пытаются сделать это сами, когда дело доходит до 'XML', который в любом случае уходит в совершенно неправильном направлении и пытается взломать его с помощью регулярных выражений. – Sobrique

ответ

1

Если предположить, что XML фактически является действительным (ваш пример не - я вам пришлось исправлять некоторые теги вручную). Затем вам следует использовать синтаксический анализатор XML. Как вы уже помечено Perl, я предполагаю, что Perl-ответ приемлемо:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use XML::Twig; 

my $twig = XML::Twig->parsefile('your_file.xml'); 

#find and iterate all the 'skin' elements. 
foreach my $skin ($twig->get_xpath('//skin')) { 
    #Check the 'att' element with these particular attributes. E.g. Name, sknLblG3S3 
    if ($skin->get_xpath('./att[@name="Name"][@value="sknLblG3S3"]')) { 
     #select the att with a name of 'Background_Colour' 
     my $bg_att = $skin->get_xpath('./att[@name="Background_color"]', 0); 
     #modify the attribute 'value'. 
     $bg_att->set_att('value', "123,456,789"); 
    } 
} 

#set output formatting - note, this can break with certain XML elements, which you don't seem to have. 
$twig->set_pretty_print('indented'); 
$twig->print; 

Вы можете перебирать в att элементы с $skin -> children(), если вы найдете его легче читать, и метод att в XML :: Twig читает атрибутов. Я чувствую, что xpath более ясен в этом примере.

(Возможно, вы также можете сделать более сложную инструкцию xpath, чтобы соответствовать дочерним/сиблям, но я не уверен, что это помогло бы читаемости).

+0

На самом деле это то, что наш XML-файл хотел бы (мы используем это для наших мобильных приложений). Просто, что я уменьшил количество тегов att. xml-файл - это один файл и другой файл с именами определенных имен скинов. Итак, как мне взять имя для другого файла и сравнить, если это имя является одним в цикле ?? –

+0

Это совершенно другой вопрос, и вы должны, вероятно, спросить его отдельно. Но дважды проверьте, действительно ли ваш XML действителен в исходном примере, потому что то, что вы цитируете, не является. – Sobrique

0

В AWK, вы могли бы попробовать это

awk -F"=?\"?[ ]*" 'BEGIN{replace="sknLblG3S3"; newcolor="0,0,0"} 
        $4=="Name"{name=$6} 
        ($4=="Background_color" && match(replace, name)) 
         {gsub(/value="[0-9,]*"/, "value=\""newcolor"\"");} 
        {print;}' inputFile 

Вы должны определить две переменные в BEGIN -блоке:

  • replace: Имя (ы) кожи следует заменить, например, replace="name,sknLblG3S3"
  • newcolor: новый цвет фона
+0

... но вы действительно не должны этого делать, потому что синтаксический анализ XML, основанный на регулярном выражении, является грязной привычкой. – Sobrique