Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Сложная замена текста в файле (http://forum.oszone.net/showthread.php?t=292761)

niverprof 19-12-2014 06:37 2445598

Сложная замена текста в файле
 
Вложений: 1
имеется файл 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 2445709

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
В идеале »

Не очень понятно. Поясните.

niverprof 19-12-2014 14:12 2445733

Цитата:

Цитата Iska
Не очень понятно. Поясните. »

Вначале 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 2445737

niverprof, в xml нет таких понятий как «параметр», «столбец» и т.п. Есть понятия «корень», «узел», «атрибут», «значение атрибута».

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

niverprof 19-12-2014 15:21 2445770

Цитата:

Цитата Iska
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 2445779

niverprof, это уже сделано в скрипте выше на PowerShell.

Непонятна вторая часть, со слов:
Цитата:

Цитата niverprof
В идеале ещё нужно »

и далее.

niverprof 19-12-2014 16:01 2445794

Цитата:

Цитата Iska
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 2446016

niverprof, ага, начинаю теперь понимать связь, на свежую голову… Попробую изобразить.

Iska 22-12-2014 01:33 2446657

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 2446719

Цитата:

Цитата Iska
Пробуйте. Проверок соответствия формата никаких. »

"
Все работает только с русским текстом беда. В исходном файле например в атрибуте "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 2446741

Цитата:

Цитата niverprof
только с русским текстом беда. В исходном файле например в атрибуте "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» ;).

А беда — вот это:
Цитата:

Цитата niverprof
и при дальнейшем импорте в базу из за кодировки вместо русских букв вопросики ??????? »

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

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

niverprof 22-12-2014 11:45 2446757

Цитата:

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

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


Время: 17:44.

Время: 17:44.
© OSzone.net 2001-