Показать полную графическую версию : [решено] Поиск <строки> в XML
В файле надо найти строку, например:
<WIDTH int="800" />
и заменить её на
<WIDTH int="1024" />
Но лучше найти с неизвестным значением.
Я думаю здесь можно пропарсить по открытию тега "<" плюс имя "WIDTH int="
и собственно по закрытию /> И перезаписать найденный шаблон строки.
Нечто такое, только без ошибок можно?
$file = FileOpen("C:\I\WinSxS\Process\Application Data\codeblocks\default.conf",0)
$i = 0
While $i <> 1
FileSetPos($file,$i,0)
$i = $i + 1
$str = FileRead($file,1)
If StringCompare($str,"<",0) then MsgBox(0,"",$str,"","")
WEnd
FileClose($file)
я тут начал побайтно искать "<" только в качестве примера... искать надо конечно же <WIDTH int="
Файл собой представляет типичный XML
Здесь мы уже решали однажды проблему, но там обошлось хитростью с IniWright. Но тут это врядли поможет.
Кстати, может кто знает что за файл лежит system32\xmlparser.exe
Может этим как-то можно пользоваться для такой задачи?
Самое главное чуть не забыл, я именно хотел организовать побайтное сравнение, чтобы найти начало строки.
И потом если начало найдено, то найти и сравнить строку итд...
Иначе если с помощью ReadFile читать, то можно наткнуться на пробелы и отступы итп.
Вообщем я думаю надо искть "<" и ">", а потом дополнительно парсить то что внутри.
Скорость работы скрипта вообщем-то не важно. Помогите такой скрипт зделать? Или какие идеи есть ещё.
:)
В файле надо найти строку, например:
<WIDTH int="800" />
и заменить её на
<WIDTH int="1024" />
Но лучше найти с неизвестным значением. »
$sFile = "C:\I\WinSxS\Process\Application Data\codeblocks\default.conf"
$sText = FileRead($sFile)
$sText = StringRegExpReplace($sText, '(?i)<WIDTH\s+int="\d+"\s*/>', '<WIDTH int="1024" />')
If @extended Then
$hFile =FileOpen($sFile,2)
FileWrite($hFile,$sText)
FileClose($hFile)
EndIf
Спасибо большое, очень полезный скрипт! Некоторые программы не используют реестр, так к ним не подобраться без этого было! :)
А можно как-то многостроковые блоки выхватывать из XML, так как я боюсь что такое мне тоже наверняка встретится. Я имею ввиду где начало "<" и завершение "/>" внутри содержат @CRLF строчки? Искать по контенту, например, найти:
"<FFFF" конец будет само собой первый попавшийся тэг "/>"
Если файл действительно содержит xml, то и работать с ним можно и нужно теми же средствами: Сценарии объектной модели документа DOM XML средствами OLE-Automation (http://www.script-coding.info/XMLDOMscripts.html).
А можно как-то многостроковые блоки выхватывать из XML »
можно, но нужно хорошо представлять себе структуру документа, "универсального" варианта тут нет
...либо используйте DOM, как подсказал Iska ... :)
"<FFFF" конец будет само собой первый попавшийся тэг "/>" »теги могут быть вложенными
Iska, увы, далеко не всегда доступна полная инфа о структуре документа - чаще есть только несколько примеров, на основе которых приходится строить свои предположения о возможной структуре
$sFile = @AppDataDir & "\codeblocks\default.conf"
$sText = FileRead($sFile)
$sText = StringRegExpReplace($sText, '(?i)<WIDTH\s+int="\d+"\s*/>', '<WIDTH int="'& @DesktopWidth &'" />')
If @extended Then
$hFile =FileOpen($sFile,2)
FileWrite($hFile,$sText)
FileClose($hFile)
EndIf
Хорошее начало! :)
теги могут быть вложенными »
Я всегда анализирую конфиг и тестирую потом, хотя ошибки всегда могут быть. :)
либо используйте DOM, как подсказал Iska »
Я не понял, там об инструменте ни слова не сказанно? Или я не понял, чем загружать чем править?
Это скорее для html аддонов инструкции, причём которые пишут, на м же надо их удалённо-пакетно править налету :)
?
ЗЫ Идея налету родилась! А что если вывести StringRegExpReplace() в STDINPUT консоли, зделать типа утилиту! )))
Я понимаю есть всякие PERL итп. но чисто поэкспереминтировать? Или это сложный и бажистый скрипт получиться?
Я имею ввиду зделать (AutoIt) StringRegExpReplace.exe --help :)
там об инструменте ни слова не сказанно »обычный VBS-скрипт, который при желании можно переделать на AutoIT
amel27, при возможности напиши пример "<SOMETHING" & @CRLF & "/>",
а я потом подумаю как применять, в любом случае пригодиться такое. Но я сам тоже подумаю может и сам справлюсь. Про vbs спасиб! Теперь ясно!
Кстати, говоря vbs могут не работать из-за всяких твиков системы, а autoit даже от себя не заввисим! :)
напиши пример "<SOMETHING" & @CRLF & "/>"и что с этим делать?.. в первом посте было понятно что и на что менять
Для работы с xml есть библиотека: XML DOM wrapper (COM) (http://www.autoitscript.com/forum/topic/19848-xml-dom-wrapper-com/).
и что с этим делать?.. в первом посте было понятно что и на что менять »
Сейчас попытаюсь реальный пример показать, может быть не самый удачный, но навскидку...
<gcc>
<NAME>
<str>
<![CDATA[GNU GCC Compiler]]>
</str>
</NAME>
<MASTER_PATH>
<str>
<![CDATA[C:\Program Files\mingw32]]>
</str>
</MASTER_PATH>
</gcc>
<msvctk>
<NAME>
<str>
<![CDATA[Microsoft Visual C++ Toolkit 2003]]>
</str>
</NAME>
<INCLUDE_DIRS>
<str>
<![CDATA[C:\Program Files\Microsoft Visual C++ Toolkit 2003\include;]]>
</str>
</INCLUDE_DIRS>
<LIBRARY_DIRS>
<str>
<![CDATA[C:\Program Files\Microsoft Visual C++ Toolkit 2003\lib;]]>
</str>
</LIBRARY_DIRS>
<MASTER_PATH>
<str>
<![CDATA[C:\Program Files\Microsoft Visual C++ Toolkit 2003]]>
</str>
</MASTER_PATH>
</msvctk>
Вот тут видно что два блока настроек: <gcc> < /gcc> и <msvctk>< /msvctk>, и хотелось бы пробраться к MASTER_PATH первого кампилятора, то-есть иметь возможность указать путь <![CDATA[C:\Program Files\mingw32]]> допустим на D:\Other\mingw32
Здесь можно лишь сложить все теги <gcc> + <NAME> + <str> + <![CDATA[GNU GCC Compiler]]> ...
+ <MASTER_PATH> + <str> + <![CDATA[C:\Program Files\mingw32]]>
игнорируя табуляцию и пробелы... либо удалив их либо установив свою произвольную табуляцию, чтобы отредактировать этот блок автоитом. Наверное это сложная задача, но может от того и интереснее. И тогда уже не будет непроходимых XML-ов!
:)
Вот так можно получить данные:
#include <_XMLDomWrapper.au3>
$FILE = @ScriptDir & "\test.xml"
$READ = FileRead($FILE)
$iLoad = _XMLLoadXML($READ)
If Not $iLoad Then Exit -1
$sPath = _XMLGetValue("/file/gcc/MASTER_PATH/str")
ConsoleWrite($sPath[1] & @LF)
записать обратно с этой библиотекой мне пока не удалось, поэтому вот пример с парсированием строк:
_XMLSetValue("Test.xml", "gcc/MASTER_PATH/str", "D:\Other\mingw32")
Func (http://www.autoitscript.com/autoit3/docs/keywords.htm#Func) _XMLSetValue($sFile, $sPath, $sValue)
$sRead = FileRead (http://www.autoitscript.com/autoit3/docs/functions/FileRead.htm)($sFile)
$sPattern = ''
$sData = ''
$aSplitPath = StringSplit (http://www.autoitscript.com/autoit3/docs/functions/StringSplit.htm)($sPath, '/')
For (http://www.autoitscript.com/autoit3/docs/keywords.htm#For) $i = 1 To (http://www.autoitscript.com/autoit3/docs/keywords.htm#To) $aSplitPath[0]
$sPattern &= '.*?<' & $aSplitPath[$i] & '>.*?'
Next (http://www.autoitscript.com/autoit3/docs/keywords.htm#Next)
$sData = StringRegExpReplace (http://www.autoitscript.com/autoit3/docs/functions/StringRegExpReplace.htm)($sRead, '(?si)(' & $sPattern & '\Q<![CDATA[\E).*?(\Q]]>\E).*?', '\1' & StringReplace (http://www.autoitscript.com/autoit3/docs/functions/StringReplace.htm)($sValue, '\', '\\') & '\2')
$hFile = FileOpen (http://www.autoitscript.com/autoit3/docs/functions/FileOpen.htm)($sFile, 2)
FileWrite (http://www.autoitscript.com/autoit3/docs/functions/FileWrite.htm)($hFile, $sData)
FileClose (http://www.autoitscript.com/autoit3/docs/functions/FileClose.htm)($hFile)
EndFunc (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndFunc)
semiono, как-то так:
$sFile = "1.xml"
$sText = FileRead($sFile)
$sRExp = '(?ims)('& _
'(?>^\s*+<gcc>).*?'& _
'(?>^\s*+<MASTER_PATH>).*?'& _
'(?>^\s*+<str>).*?'& _
'(?>^\s*+<!\[CDATA\[))' & '([^]]*+)' & '(.*?'& _
'(?>^\s*+</gcc>)'& ')'
$sText = StringRegExpReplace($sText, $sRExp, "$1D:\\Other\\mingw32$3")
If @extended Then
$hFile =FileOpen($sFile,2)
FileWrite($hFile,$sText)
FileClose($hFile)
EndIf
всё-таки для работы с DOM нужен полный файл, а не его кусок
amel27, невозможно использовать переменные, sRExp удаляет слеши в пути:
$sText = StringRegExpReplace($sText, $sRExp, "$1"& @ProgramFilesDir &"\\mingw32$3")
А без переменных ничего хорошего не напишешь, надо что-то придумать тут!
Я в паттернах не шарю, сам не смогу поправить.
Кстати, не очень понятно зачем надо \ фильтровать, ведь в шаблоне файла только прямые / слеши?
Или это фитча в StringRegExpReplace()
надо что-то придумать тут! »
То что “я придумал” в своём сообщений не подходит?
$sText = StringRegExpReplace($sText, $sRExp, "$1"& StringReplace(@ProgramFilesDir, "\", "\\") &"\\mingw32$3")
записать обратно с этой библиотекой мне пока не удалось, »
Я не стал доделывать то что не удалось, уж мне-то тем более не удалось бы.
А вот сейчас хороший вариант! :)
Ой, стоп! Я не понял, я думал это не рабочий пример...
поэтому вот пример с парсированием строк: »
Блин, я не сообразил. Я тугодум :)
Я извиняюсь, вот ещё один пример реальный надо доделать. И тему можно закрыть.
<bcc>
<NAME>
<str>
<![CDATA[Borland C++ Compiler (5.5, 5.82)]]>
</str>
</NAME>
<INCLUDE_DIRS>
<str>
<![CDATA[C:\I\Apps\Borland\CBuilder5\include;]]>
</str>
</INCLUDE_DIRS>
<LIBRARY_DIRS>
<str>
<![CDATA[C:\I\Apps\Borland\CBuilder5\lib;C:\I\Apps\Borland\CBuilder5\lib\psdk;]]>
</str>
</LIBRARY_DIRS>
<MASTER_PATH>
<str>
<![CDATA[C:\I\Apps\Borland\CBuilder5]]>
</str>
</MASTER_PATH>
</bcc>
Я боюсь испортить скрипт, тут в блоке сразу аж три строки.
Я бы сам тупо зделал три прохождения одного блока, но наверное есть способ лучше?
Должно быть так:
1. @SystemDir & "\include"
2. @SystemDir & "\lib;" & @SystemDir & "\lib\psdk"
3. @SystemDir
И спасибо ещё раз!!!
Я боюсь испортить скрипт »
А что там портить, используй функцию по назначению:
_XMLSetValue("Test.xml", "bcc/INCLUDE_DIRS/str", @SystemDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@systemdir) & "\include")
_XMLSetValue("Test.xml", "bcc/LIBRARY_DIRS/str", @SystemDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@systemdir) & "\lib;" & @SystemDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@systemdir) & "\lib\psdk")
_XMLSetValue("Test.xml", "bcc/MASTER_PATH/str", @SystemDir (http://www.autoitscript.com/autoit3/docs/macros.htm#@systemdir))
Пример.
<!-- ArrangeWindow -->
<item>
<string name="Group" value="PArrangeWindow"/>
<member name="Values">
<int name="ActiveContext Only" value="0"/>
<int name="Auto Scroll OnOff" value="1"/>
<int name="Display Format" value="0"/>
<float name="Insert Time" value="0"/>
<obj class="UPoint" name="Location" ID="182867016">
<int name="H" value="0"/>
<int name="V" value="0"/>
</obj>
<int name="Manipulate Suspends AutoScroll" value="1"/>
<int name="Multi TrackType" value="1"/>
<int name="PPQ Linear" value="0"/>
<int name="Scale Mode Film" value="3"/>
<int name="Scale Mode Frames" value="3"/>
<int name="Scale Mode PPQ" value="0"/>
<int name="Scale Mode Samples" value="3"/>
<int name="Scale Mode Seconds" value="3"/>
<int name="Show Info" value="0"/>
<int name="Show Inspector" value="1"/>
<int name="Show Overview" value="0"/>
<int name="Show Track Colors" value="1"/>
<obj class="UPoint" name="Size" ID="182564128">
<int name="H" value="1132"/>
<int name="V" value="732"/>
</obj>
<int name="Snap Mode" value="0"/>
<int name="Snap State" value="1"/>
<int name="Speaker Arr" value="1"/>
<member name="Tool Configuration">
<int name="Select Tool" value="0"/>
<int name="Range Tool" value="0"/>
<int name="Split Tool" value="-1"/>
<int name="Glue Tool" value="-1"/>
<int name="Delete Tool" value="-1"/>
<int name="Zoom Tool" value="-1"/>
<int name="Mute Tool" value="-1"/>
<int name="TimeWarp Tool" value="0"/>
<int name="Draw Tool" value="-1"/>
<int name="Curve Tool" value="0"/>
<int name="Play Tool" value="0"/>
<int name="Color Tool" value="-1"/>
<int name="SelectedToolIndex" value="0"/>
</member>
<float name="Window Zoom Factor" value="0.021212121212121212"/>
</member>
</item>
Здесь нужно установить значения для "H" и для "V"
<int name="H" value="1024"/>
<int name="V" value="768"/>
Значения должны быть таковы - @DesktopWidth, @DesktopHeigh.
Просмотрел весь файл, практически схема повторяется одна и та же.
<int name="..." value="..."/>
<float name="..." value="..."/> итд.
Все заголовки вида <!-- ArrangeWindow --> , кажись это коментарий так пишется в XML.
Мне очень нужно скрипт под этот XML. :(
Creat0R, я не уверен пойдёт ли то, что ты написал без изменений?
Func _XMLSetValue($sFile, $sPath, $sValue)
...
Мне тяжело расшифровать StringRegExpReplace() паттерн, может там даже лишнее или не хватает чего?
Помоги под эту задачу, покажи как должно быть?
Кстати, скачал _XMLDomWrapper.au3 долго глядел в него, но без справки вообще ловить нечего.
Возможно там _XMLUpdateField как-то работает с полями XML, но не ясно, что именно делать :)
Я тут смотрю, в качестве заголовка идёт такое
<obj class="UPoint" name="Size" ID="182564128">
Однако ID="182564128" может изменяться, поэтому его значение надо игнрировать.
Вобщем нужен шаблон чтобы привести к такому виду грубо говоря
<!-- ArrangeWindow --> (это тоже должно быть, ато там и другие секции есть)
...
начало: <obj class="UPoint" name="Size" ID="????">
<int name="H" value="@DesktopHeight"/>
<int name="V" value="@DesktopWidth"/>
конец: </obj>
По-моему код может быть таким -
Рид файл
компаре стринг
иф <!-- ArrangeWindow --> = 1
тогда
компаре стринг
итд.
сравниваем строки и двигаемся вперёд. ??
:)
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.