Войти

Показать полную графическую версию : Сложная замена текста в файле


niverprof
19-12-2014, 06:37
имеется файл archive_dbf.xml в нем в одну строку записаны данные, нужно найти FRM_REFL="тут 16 чисел указанных через ;" и заменить на R_400="превое число" R_420="второе число" ...... R_700="шестнадцатое число" шаг между R +20, причем после этого поиск продолжится пока снова не встретится FRM_REFL с уже новыми значениями которые тоже нужно заменить и так до конца файла.

P/S/ По сути скрипт должен менять структуру xml и делать из одного параметра FRM_REFL 16 параметров от R_400 до R_700 при этом значения для R_ХХХ берутся из FRM_REFL
В идеале ещё нужно найти <FIELD attrname="FRM_REFL" fieldtype="string.uni" WIDTH="256"/> и заменить <FIELD attrname="R_400" fieldtype="string.uni" WIDTH="256"/><FIELD attrname="R_420" fieldtype="string.uni" WIDTH="256"/> ..... <FIELD attrname="R_700" fieldtype="string.uni" WIDTH="256"/>

Файл прикладываю.

Iska
19-12-2014, 13:25
PowerShell:
$sSourceFile = "C:\Песочница\058\archive_dbf.xml"

if(Test-Path -Path $sSourceFile -PathType "Leaf") {
$oXML = [xml](Get-Content $sSourceFile)

$oXML.DATAPACKET.ROWDATA.ROW |`
ForEach-Object -Process {
$oNode = $_
$aValues = $oNode.FRM_REFL

$oNode.RemoveAttribute("FRM_REFL")

$aValues -split ";" | Where-Object -FilterScript {$_ -ne ""} | `
ForEach-Object -Begin { $i = 400 } -Process {
$oNode.SetAttribute("R_$i", $_)
$i += 20
}
}

Rename-Item -Path $sSourceFile -NewName "$sSourceFile.bak" -Force
$oXML.save($sSourceFile)
}

В идеале »
Не очень понятно. Поясните.

niverprof
19-12-2014, 14:12
Не очень понятно. Поясните. »

Вначале xml создает столбцы например <FIELD attrname="FRM_REFL" fieldtype="string.uni" WIDTH="256"/> а потом строки например
<ROWDATA><ROW ID=" 184" DATAID="1227253747" PROD_ID=" 1" SUBP_ID=" 1" UNIT="1" FRACTION="1" WEIGHTMODE="FALSE" KEY1="M1019" KEY2="Mekran" KEY3="Ral 1019" BASE_ID=" 1" FILL_QC="0" FILL_WC="0" CAN_ID=" 0" CAN_WEIGHT="FALSE" NOM_Q0="300" FORMULA="1,39.35,2,2.4,4,15.8,6,4.5,10,0.15" PART="0" SUBSTR_ID=" 0" FRM_REFL="14.675;16.731;18.792;20.047;20.389;21.760;24.031;26.392;28.912;31.025;31.398;30.927;30.581;30.288;30 .246;30.348;" X_02="26.79" Y_02="27.64" Z_02="21.26" X_10="26.57" Y_10="27.12" Z_10="20.74" DATA1="20120521" BAS_WEIGHT="FALSE" BASFILLQ="0" BASFILLW="0" BASSPEC_W="0" CUSCAN_DES="300 ml. - Обычный размер"/>

Так вот если столбцов R_400 ... R_700 не будет создано, то вероятно что и строчки в которых станет на 16 значений больше могут сбится при дальнейшей работе с файлом.

Iska
19-12-2014, 14:16
niverprof, в xml нет таких понятий как «параметр», «столбец» и т.п. Есть понятия «корень», «узел», «атрибут», «значение атрибута».

Перевести на русский выражение «Вначале xml создает» не смог вовсе. Сожалею.

niverprof
19-12-2014, 15:21
niverprof, в xml нет таких понятий как «параметр», «столбец» и т.п. Есть понятия «корень», «узел», «атрибут», «значение атрибута».
Перевести на русский выражение «Вначале xml создает» не смог вовсе. Сожалею. »

ОК давайте так. Предложенный XML по сути таблица данных. В ней есть элементы <FIELD>. Каждый элемент <FIELD> описывает содержимое определенного поля данных. Поле может быть сопоставлено только с одним столбцом таблицы. соответственно так как мне необходимо разбить один элемент <FIELD> на шестнадцать нужно например преобразовать элемент <FIELD attrname="FRM_REFL"> в <FIELD attrname="R_400"> и добавить ещё 15 элементов <FIELD attrname="R_420"> ... <FIELD attrname="R_700"> после этого идем дальше.

Элемент <ROW> описывает, как создавать строки данных из файла данных, который импортируется в таблицу. в каждом элементе <ROW> мы заменяем один атрибут FRM_REFL= на шестнадцать атрибутов R_XXX, значения которых берем из FRM_REFL= путем разделения по признаку ;

Надеюсь так стало понятнее. За скрипт огромное спасибо поставил PowerShell разобрался как работает, скрипт отработал на ура все поделилось так как хотел! осталось только создать <FIELD attrname="R_XXX">

Iska
19-12-2014, 15:39
niverprof, это уже сделано в скрипте выше на PowerShell.

Непонятна вторая часть, со слов:
В идеале ещё нужно »
и далее.

niverprof
19-12-2014, 16:01
niverprof, это уже сделано в скрипте выше на PowerShell.
Непонятна вторая часть, со слов:
Цитата niverprof:
В идеале ещё нужно »
и далее. »

Скрипт переделывает только <ROW> с ними действительно все круто, так как надо.

а вот <FIELD> остался без изменений, нужно удалить <FIELD attrname="FRM_REFL" fieldtype="string.uni" WIDTH="256" />
и создать <FIELD attrname="R_$i" fieldtype="string.uni" WIDTH="256" /> где $i = 400 с шагом 20 и концом 700.

Iska
20-12-2014, 09:48
niverprof, ага, начинаю теперь понимать связь, на свежую голову… Попробую изобразить.

Iska
22-12-2014, 01:33
niverprof, ну, вот, если ничего не забыл — как-то так:
$sSourceFile = "E:\Песочница\0417\archive_dbf.xml"

if(Test-Path -Path $sSourceFile -PathType "Leaf") {
$oXML = [xml](Get-Content $sSourceFile)

$oFieldNode = $oXML.SelectSingleNode("/DATAPACKET/METADATA/FIELDS/FIELD[@attrname='FRM_REFL']")
$oPreviousFieldNode = $oFieldNode.PreviousSibling

$oFieldNode.ParentNode.RemoveChild($oFieldNode) | Out-Null

for($i = 400; $i -le 700; $i += 20) {
$oPreviousFieldNode = $oPreviousFieldNode.ParentNode.InsertAfter($oXML.CreateNode([System.Xml.XmlNodeType]::Element, "FIELD", ""), $oPreviousFieldNode)

$oPreviousFieldNode.Attributes.Append($oXML.CreateNode([System.Xml.XmlNodeType]::Attribute, "attrname", "")).Value = "R_$i"
$oPreviousFieldNode.Attributes.Append($oXML.CreateNode([System.Xml.XmlNodeType]::Attribute, "fieldtype", "")).Value = "string.uni"
$oPreviousFieldNode.Attributes.Append($oXML.CreateNode([System.Xml.XmlNodeType]::Attribute, "WIDTH", "")).Value = "256"
}

$oXML.DATAPACKET.ROWDATA.ROW |`
ForEach-Object -Process {
$oRowNode = $_
$oAttributeNode = $oRowNode.GetAttributeNode("FRM_REFL")

$oAttributeNode.Value -split ";" | Where-Object -FilterScript {$_ -ne ""} | `
ForEach-Object -Begin {
$i = 400
$oPreviousAttributeNode = $oAttributeNode
} -Process {
$oPreviousAttributeNode = $oRowNode.Attributes.InsertAfter($oXML.CreateNode([System.Xml.XmlNodeType]::Attribute, "R_$i", ""), $oPreviousAttributeNode)
$oPreviousAttributeNode.Value = $_
$i += 20
}
$oRowNode.RemoveAttributeNode($oAttributeNode) | Out-Null
}

Remove-Item -Path "$sSourceFile.bak" -Force -ErrorAction SilentlyContinue
Rename-Item -Path $sSourceFile -NewName "$sSourceFile.bak"

$oXML.save($sSourceFile)
} else {
Write-Host "Can't find source xml file [$sSourceFile]." -ForegroundColor Red
}
Пробуйте. Проверок соответствия формата никаких.

niverprof
22-12-2014, 09:40
Пробуйте. Проверок соответствия формата никаких. »
"
Все работает только с русским текстом беда. В исходном файле например в атрибуте "CUSCAN_DES" надпись на русским выглядит как
CUSCAN_DES="500 ml. - & #1054;& #1073;& #1099;& #1095;& #1085;& #1099;& #1081; & #1088;& #1072;& #1079;& #1084;& #1077;& #1088;" а после обработки
CUSCAN_DES="500 ml. - Обычный размер" и при дальнейшем импорте в базу из за кодировки вместо русских букв вопросики ???????
как сделать чтобы обработка выкладывала то что взяла без изменений, или проще кодировку поменять в XML?

Iska
22-12-2014, 10:43
только с русским текстом беда. В исходном файле например в атрибуте "CUSCAN_DES" надпись на русским выглядит как
CUSCAN_DES="500 ml. - & #1054;& #1073;& #1099;& #1095;& #1085;& #1099;& #1081; & #1088;& #1072;& #1079;& #1084;& #1077;& #1088;" а после обработки
CUSCAN_DES="500 ml. - Обычный размер" »
niverprof, это не беда, это счастье. Теперь буду знать, чем можно вернуть кириллицу после сохранения проекта из-под «HTML Help Workshop» ;).

А беда — вот это:
и при дальнейшем импорте в базу из за кодировки вместо русских букв вопросики ??????? »
— то, что Ваше приложение не умеет корректно работать с кодировкой в XML, из-за чего Вам приходится в нём пользовать entities для кириллицы.

К сожалению, навскидку не нашёл ничего подходящего для решения такой проблемы.

niverprof
22-12-2014, 11:45
К сожалению, навскидку не нашёл ничего подходящего для решения такой проблемы. »

Ну смена кодировки это всегда определенная историю, в любом случае спасибо за скрипт, работает здорово и делает то что необходимо. С кодировкой попробую что-то придумать.




© OSzone.net 2001-2012