Что нового

[Данные, строки] изменение значения поля в XML файле

dimidron11

Новичок
Сообщения
6
Репутация
0
Версия AutoIt: 3.3.8.1

Описание: Необходим скрипт для изменения полей файла XML.
Нужно в поле с номером DOCUMENTNUMBER="937", вставить три последние цифры из ближайшего поля PAYERACCOUNTNUMBER="20005БУ0123" чтобы получилось DOCUMENTNUMBER="123937". И так по всему файлу.
Код:
<?xml version="1.0" encoding="Windows-1251"?>
<EXTRWT>
	<WTFORMAT VERSION="1.1">
		<DOCAZKAUBUCASHREQUESTS>
			<DOCAZKAUBUCASHREQUEST ADVANCEPAYMENT="0" BUDGETNAME="Бюджет Нского района" CHECKFIOBOSSNAME="Мельникова О.А." CHECKFIOGLAVBUHNAME="Вапвар Е.С" CHECKPOSITIONBOSSNAME="Заведующая" CHECKPOSITIONGLAVBUHNAME="Главный бухгалтер" CHECKSIGNATUREDATE="2012-10-11" DOCCLASS="195" DOCUMENTDATE="2012-10-09" DOCUMENTNUMBER="40" GROUND="Приобр.прод.пит. по дог.№4 от 03.07.12г., сч.ф.№680 от 19.09.12г., сч.ф.N721 от 01.10.12г. за окт. 12г." LIMCARRYDATE="2012-10-18" LINKDOCDATE="" LINKDOCNUMBER="" NDS="0" OPERKINDID="01" OPERTYPEID="0" PAYDOCCODE="" PAYERACCOUNTNUMBER="20007БУ0550" PAYERBIC="041012001" PAYERCORACCOUNT="" PAYERINN="1212003936" PAYERKPP="121201001" PAYERNAME="Муниципальное дошкольное образовательное бюджетное учреждение детский сад &quot;Машка&quot; п. Нскогочи" PAYIDENTDOCUMENTDATE="" PAYIDENTDOCUMENTNUMBER="" PAYIDENTGROUND="" PAYIDENTOKATO="" PAYIDENTPERIOD="" PAYIDENTSTATUS="" PAYIDENTTYPE="" PAYKINDNAME="электронно" PI_BUDGET_CODE="" PKVKDATE="" PKVKNUMBER="" QUEUEKIND="6" RECEIVERACCOUNTNUMBER="40802810744000000812" RECEIVERBANKBRANCHNAME="" RECEIVERBIC="041012713" RECEIVERCORACCOUNT="30101810200000000713" RECEIVERINN="121200008159" RECEIVERKPP="121201001" RECEIVERNAME="Индивидуальный предприниматель Сыченко Нина Николаевна" REMARK="" WOSPENDING="0">
				<LINES>
					<LINE AMOUNT="7898" DESCRIPTIONLINES="Договор № 4 от 03.07.12г." GRANTINVESTMENTCODE="0" GROUNDLINES="" INDUSTRYCODE="0" KESR="340" KIF="2"/>
				</LINES>
			</DOCAZKAUBUCASHREQUEST>
			<DOCAZKAUBUCASHREQUEST ADVANCEPAYMENT="0" BUDGETNAME="Бюджет Нского района" CHECKFIOBOSSNAME="Канова С.Ю" CHECKFIOGLAVBUHNAME="Вапвар Е.С." CHECKPOSITIONBOSSNAME="Директор" CHECKPOSITIONGLAVBUHNAME="главный бухгалтер" CHECKSIGNATUREDATE="2012-10-29" DOCCLASS="195" DOCUMENTDATE="2012-10-29" DOCUMENTNUMBER="1279" GROUND="Возврат денежных средств на модернизацию за 12г." LIMCARRYDATE="2012-11-07" LINKDOCDATE="" LINKDOCNUMBER="" NDS="0" OPERKINDID="01" OPERTYPEID="0" PAYDOCCODE="" PAYERACCOUNTNUMBER="21007БУ0450" PAYERBIC="041012001" PAYERCORACCOUNT="" PAYERINN="1212003887" PAYERKPP="121201001" PAYERNAME="Муниципальное общеобразовательное бюджетное учреждение Нскогочинская средняя общеобразовательная школа №2" PAYIDENTDOCUMENTDATE="0" PAYIDENTDOCUMENTNUMBER="0" PAYIDENTGROUND="0" PAYIDENTKODDOHKADMD="007" PAYIDENTKODDOHKD="07024362101612" PAYIDENTKODDOHKESD="241" PAYIDENTOKATO="0" PAYIDENTPERIOD="0" PAYIDENTSTATUS="8" PAYIDENTTYPE="0" PAYKINDNAME="электронно" PI_BUDGET_CODE="00707024362101612241" PKVKDATE="" PKVKNUMBER="" QUEUEKIND="6" RECEIVERACCOUNTNUMBER="03233010940" RECEIVERBANKBRANCHNAME="" RECEIVERBIC="041012001" RECEIVERCORACCOUNT="" RECEIVERINN="1212000903" RECEIVERKPP="121201001" RECEIVERNAME="Отдел образования администрации Нского района" REMARK="" WOSPENDING="0">
				<LINES>
					<LINE AMOUNT="15616" DESCRIPTIONLINES="" GRANTINVESTMENTCODE="058" GROUNDLINES="" INDUSTRYCODE="0" KESR="226" KIF="5"/>
				</LINES>
			</DOCAZKAUBUCASHREQUEST>
		</DOCAZKAUBUCASHREQUESTS>
	</WTFORMAT>
</EXTRWT>

Примечания: В файле может быть неограниченное количество данных. Изменению подлежат все файлы в данной папке (из которой запущен скрипт).


Добавлено:
Сообщение автоматически объединено:

Товарищи помогите в решении моей задачи :(

Вижу решение моей задачи вот так:

Создать массив из 30 пунктов:
A=CHECKFIOBOSSNAME="Мельникова О.А."
B=CHECKFIOBOSSNAME="Канова С.Ю"
C=...

Значения для подстановки:
если A то 550
если B то 450
если C то ....


если первое значение в строке CHECKFIOBOSSNAME="Мельникова О.А." то заменить DOCUMENTNUMBER=" на DOCUMENTNUMBER="550

потом проверить чему равно следующее значение CHECKFIOBOSSNAME и если оно CHECKFIOBOSSNAME="Канова С.Ю", то заменить DOCUMENTNUMBER=" на DOCUMENTNUMBER="450
и так до конца документа. Но как это реализовать :blink:
 

darkwhite

Знающий
Сообщения
129
Репутация
5
что то не пойму прочитал и вижу 2 задачи
1. поменять DOCUMENTNUMBER="937" подставив 3 цифры из PAYERACCOUNTNUMBER="20005БУ0123"
2. поменять DOCUMENTNUMBER=" на DOCUMENTNUMBER="550 если CHECKFIOBOSSNAME="Мельникова О.А."

какую из них решаем то ?
 
Автор
D

dimidron11

Новичок
Сообщения
6
Репутация
0
А это два метода для одной задачи.
1. В номер добавляется три цифры в зависимости от значения из PAYERACCOUNTNUMBER.
2. В номер добавляется три цифры в зависимости от значения из CHECKFIOBOSSNAME.

PAYERACCOUNTNUMBER = № лицевого счета.
CHECKFIOBOSSNAME = фамилия руководителя.

И в том и другом варианте эти три цифры одинаковые, т.к. фамилия руководителя и № лицевого счета всегда соответствуют друг другу. Но второй вариант наверное легче реализовать (я так думаю, потому что значение с фамилией перед значением Номера документа в строке).
 

Yuri

AutoIT Гуру
Сообщения
737
Репутация
282
Вот один из способов решения. Тестируй.
Код:
#include <File.au3>
#include <String.au3>

$FileList =_FileListToArray(@ScriptDir, "*.xml")
If $FileList = 0 Then
   MsgBox(48, "Инфо", "Файлы xml не найдены")
   Exit
Else
   For $i = 1 To $FileList[0]	  
	  WriteXML($FileList[$i])
   Next
EndIf

Func WriteXML($File)   
   Local $aRecords
   _FileReadToArray($File, $aRecords)  
   For $i = 1 To $aRecords[0]
	  $StrPos_1 = StringInStr($aRecords[$i], 'DOCUMENTNUMBER="')
	  $StrPos_2 = StringInStr($aRecords[$i], 'PAYERACCOUNTNUMBER="')
	  If  $StrPos_1 And $StrPos_2 Then		 
		 $DocNum = _StringBetween($aRecords[$i], 'DOCUMENTNUMBER="', '" GROUND=')
		 $PayAccNum = _StringBetween($aRecords[$i], 'PAYERACCOUNTNUMBER="', '" PAYERBIC=')
		 $Str_3_PAN = StringRight($PayAccNum[0], 3)
		 $Str_3_DN = StringLeft($DocNum[0], 3)		 
			;If $Str_3_PAN <> $Str_3_DN Then
			   $aRecords[$i] = _StringInsert($aRecords[$i], $Str_3_PAN, $StrPos_1 + 15)			   			   
			;EndIf   
	  EndIf
   _FileWriteFromArray($File, $aRecords, 1)   
   Next
EndFunc

MsgBox(64, "Инфо", "Готово"&@CRLF&"Обработано "&$FileList[0]&" файлов")
 
Автор
D

dimidron11

Новичок
Сообщения
6
Репутация
0
Yuriy :ok: вроде всё как надо. Результат полноценного тестирования на больших файлах смогу сообщить только завтра. :IL_AutoIt_1:
Еще бы глянуть как можно решить эту задачу вторым способом, с массивом (на будущее ;))


Добавлено:
Сообщение автоматически объединено:

Можно ли узнать сколько подстановок было произведено в файле?
 

XpycT

Скриптер
Сообщения
380
Репутация
133
dimidron11
Вот еще один способ решения ващей задачи

Код:
Global $sXML_Org = @ScriptDir & "\file_org.xml"
Global $sXML_Rem = @ScriptDir & "\file_rem.xml"
If FileExists($sXML_Rem) Then FileDelete($sXML_Rem)

Global $oXML = ObjCreate("Msxml2.DOMDocument.6.0")

$oXML.Load($sXML_Org)

$oNodes = $oXML.SelectNodes("EXTRWT/WTFORMAT/DOCAZKAUBUCASHREQUESTS/DOCAZKAUBUCASHREQUEST")
If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oXML.SelectNodes | Error > " & $oXML.ParseError.Reason & @CR)

For $oNode In $oNodes
	$sCHECKFIOBOSSNAME   = $oNode.GetAttribute("CHECKFIOBOSSNAME")   ; CHECKFIOBOSSNAME
	$sPAYERACCOUNTNUMBER = $oNode.GetAttribute("PAYERACCOUNTNUMBER") ; PAYERACCOUNTNUMBER

	$sDOCUMENTNUMBER_Old = $oNode.GetAttribute("DOCUMENTNUMBER")     ; DOCUMENTNUMBER Old
	$sDOCUMENTNUMBER_New = StringRight($sPAYERACCOUNTNUMBER, 3) & $sDOCUMENTNUMBER_Old

; 	$sDOCUMENTNUMBER_Old = $oNode.GetAttribute("DOCUMENTNUMBER")     ; DOCUMENTNUMBER Old
; 	$sDOCUMENTNUMBER_New = StringRight($sPAYERACCOUNTNUMBER, 3)

	ConsoleWrite("$sCHECKFIOBOSSNAME = " & $sCHECKFIOBOSSNAME & " | $sPAYERACCOUNTNUMBER = " & $sPAYERACCOUNTNUMBER & " | $sDOCUMENTNUMBER = " & $sDOCUMENTNUMBER_Old & " > " & $sDOCUMENTNUMBER_New & @CR)

	$oNode.SetAttribute("DOCUMENTNUMBER", $sDOCUMENTNUMBER_New)
Next

$oXML.Save($sXML_Rem)
 
Автор
D

dimidron11

Новичок
Сообщения
6
Репутация
0
Спасибо большое за помощь :beer:. Замена происходит и по скрипту от Yuriy и от XpycT :ok:.
+ у Yuriy обрабатываются все файлы .xml в папке и может быть применима к любым txt файлам.
+ у XpycT обработка быстрее и работает с конкретными полями XML.

Осталось разобраться с:
1. Как добавить информацию о количестве произведенных замен.
2. И как добавлять произвольные цифры в зависимости от фамилии (о чем писал выше). :scratch:
 

eropov

Jury
Сообщения
195
Репутация
25
Осталось разобраться с:
1. Как добавить информацию о количестве произведенных замен.
2. И как добавлять произвольные цифры в зависимости от фамилии (о чем писал выше).

Код:
Global $sXML_Org = @ScriptDir & "\1.xml"
Global $sXML_Rem = @ScriptDir & "\file_rem.xml"
If FileExists($sXML_Rem) Then FileDelete($sXML_Rem)

Global $oXML = ObjCreate("Msxml2.DOMDocument.6.0")
Global $i = 0
$oXML.Load($sXML_Org)

$oNodes = $oXML.SelectNodes("EXTRWT/WTFORMAT/DOCAZKAUBUCASHREQUESTS/DOCAZKAUBUCASHREQUEST")
If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oXML.SelectNodes | Error > " & $oXML.ParseError.Reason & @CR)

For $oNode In $oNodes
	$sCHECKFIOBOSSNAME = $oNode.GetAttribute("CHECKFIOBOSSNAME") ; CHECKFIOBOSSNAME
	$sPAYERACCOUNTNUMBER = $oNode.GetAttribute("PAYERACCOUNTNUMBER") ; PAYERACCOUNTNUMBER

	$sDOCUMENTNUMBER_Old = $oNode.GetAttribute("DOCUMENTNUMBER") ; DOCUMENTNUMBER Old
	$sDOCUMENTNUMBER_New = StringRight($sPAYERACCOUNTNUMBER, 3) & $sDOCUMENTNUMBER_Old

	$sDOCUMENTNUMBER_Old = $oNode.GetAttribute("DOCUMENTNUMBER")     ; DOCUMENTNUMBER Old
	$sDOCUMENTNUMBER_New = StringRight($sPAYERACCOUNTNUMBER, 3)

	ConsoleWrite("$sCHECKFIOBOSSNAME = " & $sCHECKFIOBOSSNAME & " | $sPAYERACCOUNTNUMBER = " & $sPAYERACCOUNTNUMBER & " | $sDOCUMENTNUMBER = " & $sDOCUMENTNUMBER_Old & " > " & $sDOCUMENTNUMBER_New & @CR)

	$oNode.SetAttribute("DOCUMENTNUMBER", $sDOCUMENTNUMBER_New)
	$i += 1
Next

$oXML.Save($sXML_Rem)
ConsoleWrite("Информация! Количество произведенных замен : " & $i & @CRLF)
 

Yuri

AutoIT Гуру
Сообщения
737
Репутация
282
Переделал чуть свой предыдущий вариант
Код:
#include <File.au3>
#include <String.au3>
$n = 0
$FileList =_FileListToArray(@ScriptDir, "*.xml")
If $FileList = 0 Then
   MsgBox(48, "Инфо", "Файлы xml не найдены")
   Exit
Else
   For $i = 1 To $FileList[0]     
      WriteXML($FileList[$i])
   Next
EndIf

Func WriteXML($File)   
   Local $aRecords
   _FileReadToArray($File, $aRecords)  
   For $i = 1 To $aRecords[0]
      $StrPos_1 = StringInStr($aRecords[$i], 'DOCUMENTNUMBER="')      
      If  $StrPos_1 Then         
         $PayAccNum = _StringBetween($aRecords[$i], 'PAYERACCOUNTNUMBER="', '" PAYERBIC=')
         $Str_3_PAN = StringRight($PayAccNum[0], 3)                  
         $aRecords[$i] = _StringInsert($aRecords[$i], $Str_3_PAN, $StrPos_1 + 15)
		 _FileWriteToLine($File, $i, $aRecords[$i], 1)
		 $n += 1
      EndIf     
   Next
EndFunc

MsgBox(64, "Инфо", "Обработано файлов: "&$FileList[0]&@CRLF&"Произведено всего замен: "&$n)
 
Автор
D

dimidron11

Новичок
Сообщения
6
Репутация
0
в скрипте от eropov какая-то ошибка, файл создается но в нем не добавлены 3 цифры, а заменен оригинальный номер на 3 цифры и сообщение о кол-ве замен не выводится.

скрипт от Yuriy информация о кол-ве замен выдается верно, еще бы фамилии прикрутить ;).

по скорости обработки файла содержащего 741 запись:
скрипт от Yuriy выполняется за 1 мин 7 сек.
скрипт от XpycT выполняется за 4 секунды. :shok:
 

Yuri

AutoIT Гуру
Сообщения
737
Репутация
282
Т.к. скрипт от XpycT работает гораздо быстрее,
то вот так можно. Тут сразу идет запись в исходные файлы.
Код:
#include <File.au3>
$n = 0
$FileList =_FileListToArray(@ScriptDir, "*.xml")

If $FileList = 0 Then
   MsgBox(48, "Инфо", "Файлы xml не найдены")
   Exit
Else
   Global $oXML = ObjCreate("Msxml2.DOMDocument.6.0")
   For $i = 1 To $FileList[0]     
      Msxml($FileList[$i])
   Next
EndIf

Func Msxml($File)
   $oXML.Load($File)
   $oNodes = $oXML.SelectNodes("EXTRWT/WTFORMAT/DOCAZKAUBUCASHREQUESTS/DOCAZKAUBUCASHREQUEST")
   If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oXML.SelectNodes | Error > " & $oXML.ParseError.Reason & @CR)
   For $oNode In $oNodes
	  $sCHECKFIOBOSSNAME   = $oNode.GetAttribute("CHECKFIOBOSSNAME")   ; CHECKFIOBOSSNAME
	  $sPAYERACCOUNTNUMBER = $oNode.GetAttribute("PAYERACCOUNTNUMBER") ; PAYERACCOUNTNUMBER
	  $sDOCUMENTNUMBER_Old = $oNode.GetAttribute("DOCUMENTNUMBER")     ; DOCUMENTNUMBER Old
	  $sDOCUMENTNUMBER_New = StringRight($sPAYERACCOUNTNUMBER, 3) & $sDOCUMENTNUMBER_Old    
	  $oNode.SetAttribute("DOCUMENTNUMBER", $sDOCUMENTNUMBER_New)
	  $n += 1
   Next
   $oXML.Save($File)
EndFunc

MsgBox(64, "Инфо", "Обработано файлов: "&$FileList[0]&@CRLF&"Произведено всего замен: "&$n)




Добавлено:
Сообщение автоматически объединено:

Если в зависимости от фамилий и еще с использованием массива,
то как-то так
Код:
#include <File.au3>
Dim $Array [2][2] = [["Мельникова О.А.", "Канова С.Ю"], [550, 450]] 
$n = 0
$FileList =_FileListToArray(@ScriptDir, "*.xml")

If $FileList = 0 Then
   MsgBox(48, "Инфо", "Файлы xml не найдены")
   Exit
Else
   Global $oXML = ObjCreate("Msxml2.DOMDocument.6.0")
   For $i = 1 To $FileList[0]     
      Msxml($FileList[$i])
   Next
EndIf

Func Msxml($File)
   $oXML.Load($File)
   $oNodes = $oXML.SelectNodes("EXTRWT/WTFORMAT/DOCAZKAUBUCASHREQUESTS/DOCAZKAUBUCASHREQUEST")
   If $oXML.ParseError.ErrorCode <> 0 Then Exit 99 * 0 + ConsoleWrite("$oXML.SelectNodes | Error > " & $oXML.ParseError.Reason & @CR)
   For $oNode In $oNodes
	  $sCHECKFIOBOSSNAME   = $oNode.GetAttribute("CHECKFIOBOSSNAME")   ; CHECKFIOBOSSNAME	  
	  Switch $sCHECKFIOBOSSNAME
		 Case $Array[0][0]
			$oNode.SetAttribute("DOCUMENTNUMBER", $Array[1][0])
			$n += 1
		 Case $Array[0][1]
			$oNode.SetAttribute("DOCUMENTNUMBER", $Array[1][1])
			$n += 1
	  EndSwitch		  
   Next
   $oXML.Save($File)
EndFunc

MsgBox(64, "Инфо", "Обработано файлов: "&$FileList[0]&@CRLF&"Произведено всего замен: "&$n)
 
Автор
D

dimidron11

Новичок
Сообщения
6
Репутация
0
Всем большое спасибо :beer:, вроде все работает как надо (быстро и качественно) :IL_AutoIt_1:
 
Верх