LinuxForum.Fans
Тема

<XML>

Автор: semiono 45 сообщений 13600 просмотров
#307333
text
      <item>
         <string name="Group" value="TransportWindow"/>
         <member name="Values">
            <obj class="UPoint" name="Location" ID="215319288">
               <int name="H" value="321"/>
               <int name="V" value="690"/>
            </obj>
         </member>
      </item>

Нужно изменить значения "H" и "V" из коммандной строки. Нашёл какие-то похожие действия с awk, но там лес кода сам не разберусь)
Хотя ещё узнать бы разрешение экрана, чтобы подставить в эти значения, но это уже второй вопрос.
И если возможно попроще, я снова спрашиваю под GnuWin32 awk, grep, sed...

То-есть имеется файл defaults.xml в котором множество блоков и надо найти именно нужный.

#307341
"semiono⇓" написал:
Нужно изменить значения "H" и "V" из коммандной строки.

Если совсем «в лоб», то можно и так:

text
sed -i'.bak' -e 's/value=\"321/value=\"123/g' -e 's/value=\"690/value=\"096/g' defaults.xml

Но это именно «в лоб»! И заметьте, файл перезаписывается, если сохранённая копия не нужна, уберите '.bak'.

"semiono⇓" написал:
Нашёл какие-то похожие действия с awk, но там лес кода сам не разберусь)

Покажите.

"semiono⇓" написал:
Хотя ещё узнать бы разрешение экрана, чтобы подставить в эти значения, но это уже второй вопрос.

Конечная цель задачи какая? Возможно, есть уже и готовые решения.

#307383
"semiono" написал:
И если возможно попроще, я снова спрашиваю под GnuWin32 awk, grep, sed...

Это, конечно, не grep, awk, sed, но вдруг пригодится.

Python 2

text
#!/usr/bin/env python
#-*- coding: utf-8 -*-

import re

newh = input('Новое значение для h? ') newv = input('Новое значение для v? ') h = str(newh) v = str(newv)

ourxml = open("defaults.xml") data = ourxml.read() ourxml.close()

varh = re.findall('<int name="H" value="(.+?)"/>', data, re.DOTALL) varv = re.findall('<int name="V" value="(.+?)"/>', data, re.DOTALL)

data = data.replace(varh[0], h) data = data.replace(varv[0], v)

ourxmlfix = open('defaults.xml', 'w') for line in data: ourxmlfix.write(line) ourxmlfix.close()

#307418

semiono, на сколько строгое должно быть решение?
абсолютно строго средствами что sed'а, что awk'а это очень геморройно... для этих целей лучше подойдёт какой-нить язык с xml-парсером (python/perl). конечно не так тупо, как у xxblx, но на них...

на sed'е можно примерно с теме же регулярками, что у xxblx, только sed ленивые регулярки не умеет, поэтому изощряться придётся:
sed 's!\(<int name="H" value="\)[^"]*\("/>\)!\1100500\2!'
но это годное для половины случаев, но не надёжное решение...

#307420

Какие-то инструменты я нашёл: http://xmlstar.sourceforge.net/
Давно хотел найти иструменты командной строки для работы с XML, хотя для этого специально пришлось поиском занятся.

#307421

А ещё просьба, а есть калькулятор или чтонибудь для вывода значений формулы в файл..
корень из двух 12 степени в степени N умноженный на 440,0 где N это {1, 2 ,3... 12}
Чтоб получился file.txt
440.00
466.16
..
880.00

#307424
"semiono⇓" написал:
А ещё просьба, а есть калькулятор или чтонибудь для вывода значений формулы в файл..
корень из двух 12 степени в степени N умноженный на 440,0 где N это {1, 2 ,3... 12}

если традиционный unix-way, то bc.
или можно тем же питоном обойтись...

#307428
"semiono⇓" написал:
То-есть имеется файл defaults.xml в котором множество блоков и надо найти именно нужный.

По какому признаку находится нужный блок?

#307432
-=Serj=- написал:
[quote="semiono⇓"]То-есть имеется файл defaults.xml в котором множество блоков и надо найти именно нужный.

По какому признаку находится нужный блок?[/quote]
Еслиб я знал, пока гадаю, я с xml не знаком. Кстати, xmlstarlet-1.4.2-win32 юникс-вей, но мне от этого не легче)

Вот примерный документ

text
<Defaults>
   <list name="Entries" type="list">

<!-- Event Image --> <item> <string name="Group" value="Event Image"/> <member name="Values"> <int name="Show Data" value="1"/> <int name="Show Names" value="0"/> <int name="Transparent" value="0"/> </member> </item>

<!-- PTrackEffectWindow --> <item> <string name="Group" value="PTrackEffectWindow"/> <member name="Values"> <obj class="UPoint" name="Location" ID="183011808"> <int name="H" value="1"/> <int name="V" value="1"/> </obj> <int name="State" value="1"/> </member> </item>

<!-- Enable Record on Select Track --> <item> <string name="Group" value="Record"/> <member name="Values"> <int name="Enable Record on Select Track" value="1"/> </member> </item>

<!-- Registration --> <item> <string name="Group" value="Registration"/> <member name="Values"> <int name="Registered 4.0" value="1"/> </member> </item>

<!-- TransportWindow --> <item> <string name="Group" value="TransportWindow"/> <member name="Values"> <obj class="UPoint" name="Location" ID="215319288"> <int name="H" value="321"/> <int name="V" value="690"/> </obj> </member> </item>

</list> </Defaults>

Напрягают строки вида <int name="H" value="1"/> где <value и name> в одном тэгге записанны,
хотя xml.exe кое какие результаты показал, тепрь на моём файле бы их применить. Изучаю пока)

Коментарии я сам добавил, надеюсь правильно:
<!-- PTrackEffectWindow -->

#307445
"Fat-Zer" написал:
для этих целей лучше подойдёт какой-нить язык с xml-парсером (python/perl). конечно не так тупо, как у xxblx, но на них...

Под "тупо" подразумевается - "слишком в лоб"?
Ну так и вариант этот не конкретно для xml, а по сути для любых текстовых файлов подойдет. Или есть более элегантный способ, работающий с любыми текстовыми файлами?

#307446

Пример: file.xml

text
<Defaults>
   <list name="Entries" type="list">

<item> <string name="Group" value="zzzz"/> <member name="Values"> <obj class="UPoint" name="Location" ID="215319288"> <int name="H" value="321"/> <int name="V" value="690"/> </obj> </member> </item>

<item> <string name="Group" value="TransportWindow"/> <member name="Values"> <obj class="UPoint" name="Location" ID="215319288"> <int name="H" value="321"/> <int name="V" value="690"/> </obj> </member> </item>

</list> </Defaults>

# xml ed -u "/Defaults/list/item/string[@value=TransportWindow]/member/obj/int[@name=H]" -v 777 file.xml

что-то не хочет

#307451
"xxblx⇓" написал:
varh = re.findall('<int name="H" value="(.+?)"/>', data, re.DOTALL)

ИМХО, флаг DOTALL как и . в регулярке здесь неуместны.

"xxblx⇓" написал:
data = data.replace(varh[0], h)
data = data.replace(varv[0], v)

Таким макаром заменятся все числа в тексте, совпавшие с найденными.

#307452
"semiono⇓" написал:
Пример: file.xml

Не пойму, значения нужно во всех вхождениях менять или только внутри элемента, содержащего

text
<string name="Group" value="TransportWindow"/>

?

#307454

В общем, если жёстко, то как-то так:

text

#!/usr/bin/env python
#_*_ coding: utf-8 _*_

import optparse import re

p = optparse.OptionParser() p.add_option("-H", action="store", type="int", dest="H") p.add_option("-V", action="store", type="int", dest="V")

opt, args = p.parse_args() fname = args[0] h = opt.H v = opt.V

with open(fname, 'r') as f: data = f.read()

patt = re.compile(r"""<item> <string name=\"Group\" value=\"TransportWindow\"/> <member name=\"Values\"> <obj class=\"UPoint\" name=\"Location\" ID=\"(\d+)\"> <int name=\"H\" value=\"\d+\"/> <int name=\"V\" value=\"\d+\"/> </obj> </member> </item>""")

ID = patt.findall(data)[0] repl = ("""<item> <string name="Group" value="TransportWindow"/> <member name="Values"> <obj class="UPoint" name="Location" ID="%s"> <int name="H" value="%s"/> <int name="V" value="%s"/> </obj> </member> </item>""" % (ID, h, v)) data = patt.sub(repl, data)

with open('new.xml', 'w') as f: f.write(data)

Запускать так:

text

$ ./parser.py -H 200 -V 100 file.xml

Создаст новый файл new.xml.

#307455

я специально зделал две похожии секции, нужно только в одной

#307463

Питон, конечно, круто, но не под windows :)
Лучше с grep+sed помогите.

вот, например, сэд:
sed -ri "/H\" value/s/[0-9]+/91/" file.xml
но мне надо ещё в нужную секцию попасть, которая распознаётся как
<string name="Group" value="TransportWindow"/>

Вобщем grep и xargs нехватает

#307478
"xxblx⇓" написал:
Под "тупо"  подразумевается - "слишком в лоб"? Ну так и вариант этот не конкретно для xml, а по сути для любых текстовых файлов подойдет. Или есть более элегантный способ, работающий с любыми текстовыми файлами?

и в лоб... и не практично и потенциально ошибки вызывает... для любых - конечно подойдёт, а для xml - нет... см. хотя бы пример ТС... такие костыли больше геморроя вызывают, чем пользы... ещё вариант -=Serj=-'а имеет больше прав на существование... только вот надо в регулярках все пробелы сделать опциональными и произвольной длины, но после этого прочитать её сможет только обкуренный перловщик...

в принципе с xml'ем работать, как с обычным текстом в полуавтоматическом режиме ИМХО моветон...

"semiono⇓" написал:
# xml ed -u "/Defaults/list/item/string[@value=TransportWindow]/member/obj/int[@name=H]" -v 777 file.xml

путь не правильный...

вот на перловке набросал вариант:

text
#!/usr/bin/perl
use XML::LibXML;

my $parser = XML::LibXML->new(); my $dom = $parser->parse_file( $ARGV[0] );

my $xp_str='/Defaults/list/item[string[@value=\'TransportWindow\']]/member/obj/int[@name=\'H\']/@value';

${$dom->documentElement()->findnodes($xp_str)}[0]->setValue('777');

open(my $out_fh, '>:raw', "out.xml") or die $!; print($out_fh $dom->toString());

#307520
"Fat-Zer⇓" написал:
только вот надо в регулярках все пробелы сделать опциональными и произвольной длины, но после этого прочитать её сможет только обкуренный перловщик...

Ну да, это упрощённый вариант, для читабельности и по-быстрому.

"Fat-Zer⇓" написал:
в принципе с xml'ем работать, как с обычным текстом в полуавтоматическом режиме ИМХО моветон...

Как скажешь:) Вот вариант с использование стандартной библиотеки xml:

text

#!/usr/bin/env python
#_*_ coding: utf-8 _*_

import optparse from xml.etree.ElementTree import parse

p = optparse.OptionParser() p.add_option("-H", action="store", type="int", dest="H") p.add_option("-V", action="store", type="int", dest="V")

opt, args = p.parse_args() fname = args[0] h = str(opt.H) v = str(opt.V)

tree = parse(fname) items = tree.findall('.//item')

for item in items: if item.find('string').attrib['value'] == 'TransportWindow': for target in item.findall('.//int'): if target.attrib['name'] == "H": target.attrib['value'] = h elif target.attrib['name'] == "V": target.attrib['value'] = v

with open('new.xml', 'w') as f: tree.write(f)

#307523
"semiono⇓" написал:
Питон, конечно, круто, но не под windows

Нет проблем.. Забирайте - http://ubuntuone.com/1Xsb5sClTWQkcuxFZGVHTR
Запускать так-же

text

xparse.exe -H <значение> -V <значение> <входной файл.xml>

На выходе будет новый файл new.xml.

#307561

Это что весь python? :)

Наверное нужен дистрибутив, он куда-то на диск C: ссылается, хотя у меня нет диска C:

text
 //xpars.exe parser.py -H 200 -V 100 file.xml
Traceback (most recent call last):
  File "<string>", line 17, in <module>
  File "C:\pyinstaller-2.0\xpars2\build\pyi.win32\xpars2\out00-PYZ.pyz\xml.etree.Element
Tree", line 1183, in parse
  File "C:\pyinstaller-2.0\xpars2\build\pyi.win32\xpars2\out00-PYZ.pyz\xml.etree.Element
Tree", line 656, in parse
  File "C:\pyinstaller-2.0\xpars2\build\pyi.win32\xpars2\out00-PYZ.pyz\xml.etree.Element
Tree", line 1643, in feed
  File "C:\pyinstaller-2.0\xpars2\build\pyi.win32\xpars2\out00-PYZ.pyz\xml.etree.Element
Tree", line 1507, in _raiseerror
xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 1, column 1

//

Войдите или зарегистрируйтесь, чтобы ответить.