2009-12-22 3 views
4

Мне интересно, есть ли способ создать пакетный файл, который может редактировать строку в документе XML. Линия будет идентифицирована предыдущей строкой. идея была бы следующей:Редактирование XML с пакетным файлом

If line == Csetting name="BaseDirectory" serializeAs="String"> 
    Next line = <value>User Input from begining of batch</value> 

что-то вроде этого даже возможно или я вижу сновидение снаружи своих средств? Спасибо за помощь и ответы.

ответ

6

Возможно, вы, возможно, могли взломать что-то вместе в пакетном файле, который работает как-то. Но это будет чрезвычайно болезненно. Прежде всего, я не знаю, как надежно считывать строки в переменные в пакетном файле и записывать их обратно в файл без изменений. Вы можете избежать большинства проблемных символов (например, <, >, &, |, ...), но все еще есть проблемы, которые я не мог решить (например, несогласованные кавычки), которые приведут к таким попыткам сбой ужасно. Тогда вы все равно не сможете анализировать XML, но вы предпочтете примитивную обработку текста, которая может легко выйти из строя, как только вместо двойных кавычек будут использоваться одинарные кавычки. Или куда-то лишнее пространство. Или линия, которую вы ищете, разделена на несколько строк. Все допустимые XML, но больно для синтаксического анализа, когда вокруг нет парсера XML.

Язык командного файла на самом деле не подходит для таких задач. Heck, он едва работает для обработки текста, но XML выходит за рамки. У вас может быть больше удачи (и весело) с использованием VBScript и MSXML или даже PowerShell (если применимо).

VBScript, вероятно, самый разумный выбор здесь, так как вы можете полагаться на него, существуя практически на любой современной машине Windows.

Вы также можете использовать XSLT и вызывать это из командной строки. Существует достаточно XSLT-процессоров, которые могут быть использованы, и генерация XSLT-файла на самом деле намного проще (но по-прежнему потребуется несколько экранов).


Обратите внимание, что я не могу быть продвинутым пользователем пакетного файла/программистом, но ни в коем случае авторитетная. Может быть, это легко возможно, и я просто слишком глуп, чтобы это увидеть.

+0

Вы правы, это невозможно при использовании стандартных окон командами партии. –

+0

его возможно. просто вам понадобится больше времени и усилий – ghostdog74

+0

Ну, проблема с цитированием/побегом в настоящее время не имеет решения для меня. Я не могу прочитать строку, такую ​​как 'a | b" <> & ', и записать ее в файл без изменений. Непревзойденные кавычки приведут к отказу обычных механизмов экранирования (' set "foo =% foo: & =^&%" ') – Joey

1

уверен, изначально, вы можете использовать пакет, но я рекомендую вам изучить и использовать VBScript вместо

Set objFS=CreateObject("Scripting.FileSystemObject") 
strFile = WScript.Arguments.Item(0) 
strUserValue= WScript.Arguments.Item(1) 
Set objFile = objFS.OpenTextFile(strFile) 
Do Until objFile.AtEndOfStream 
    strLine = objFile.ReadLine 
    If InStr(strLine,"Csetting name") >0 And _ 
     InStr(strLine,"BaseDirectory")> 0 And _ 
     InStr(strLine,"serializeAs=") > 0 Then  
     strLine=strLine & vbCrLf & "<value>" & strUserValue & "</value>"   
    End If 
    WScript.Echo strLine 
Loop 

сохранить скрипт как edit.vbs и в вашей партии

c:\test> cscript //nologo edit.vbs file "user value" 

VBScript является лучшее, что у вас есть, кроме калеки, если вы ненавидите идею использования других инструментов, таких как gawk/sed/Python/Perl или другие синтаксические анализаторы/писатели xml. В противном случае вам следует рассмотреть возможность использования этих лучших инструментов.

+0

(содрогнулся) Я не спускаюсь, но каждый раз, когда я использовал MS Basic, он был с крайне неохотой и большим разочарованием. –

+0

@Jason S - вы можете порекомендовать лучшую альтернативу, пожалуйста. Спасибо! – Adkins

+1

Если вы используете такой скрипт, отлично, но используйте XML-объект для редактирования XML, в противном случае ваша проблема экранирования останется. В VBScript нет ничего плохого - это хорошая альтернатива, если вы не может скомпилировать что-то. –

1

XML не основан на линиях, поэтому предположение, что вы можете что-то искать в файле, проверяя его поэтапно, либо подвержено проблемам, либо полагается на другие предположения, кроме XML. (если вы получаете свой файл из определенного типа программного обеспечения, как вы знаете, он всегда будет выпускать выходные линии таким образом?)

Сказав это, я взглянул на JSDB Javascript, который имеет E4X встроенный. E4X делает особенно простым манипулирование XML, если вы можете прочитать все это в памяти; это не потоковая система.Хотя вы можете использовать JSDB без E4X и обрабатывать файл ввод/вывод с использованием потоков:

var Sin = new Stream('file://c:/tmp/testin.xml'); 
var Sout = new Stream('file://c:/tmp/testout.xml','w'); 
while (!Sin.eof) 
{ 
    var Lin = Sin.readLine(); 
    var Lout = some_magic_function(Lin); // do your processing here 
    Sout.writeLine(Lout); 
} 
Sin.close(); Sout.close(); 
6

Я на самом деле быть_наст ответ на это. Да, это больно, однако у меня была аналогичная проблема, и я действительно не знаю VBScript (хотя я планирую изучить ее ...) на время, хотя моя проблема возникла с коллегой, у которой был клиент с 20 000 файлов, которые они вырвали из преобразование внешних данных. Все файлы были xml, и все они пропускали одну и ту же вторую строку XML, которая вызвала рефикс документа, который мы импортировали.

Я написал стандартный пакетный скрипт в тандеме с другим, который я нашел в StackOverflow, который позволил мне разбить файлы на 2 части, а затем между ними вставить код, который я хотел. Теперь моя единственная проблема (возможно, из-за лени или моего отсутствия знания/терпения) заключалась в том, что я не мог избежать проблемы <. Сценарий продолжал думать, что я пытался записать файл, что было неверно. Я пробовал всевозможные способы использования этого символа, но я хотел его в переменной форме. Само собой разумеется, я получил его работу (хорошо даже) ...

Ниже приведено мое письмо моему коллеге вместе с кодом из каждого файла.

README.txt Проблема: Массивная количество файлов отсутствовали строку или фрагмент кода, который должен быть отредактирован

Решение: Этот инструмент разбирает файлы и впрыскивает строку или кусок кода а затем поместите файлы обратно в другое место.

Всего 4 файла, которые поставляются с этим инструментом.

**1 - _README.txt  - This file describes how to use the script 
    **2 - insert.txt   - This file contains the text that will be inserted into the file you need edited. 
    **3 - InsertString.bat  - This file contains the actual script that loops to restructure the file. Here you will find all the variables that need to be set to make this work. 
    **4 - String_Insert_Launcher.bat - This file is what you will launch to run the InsertString.bat file. 

Что вам нужно сделать:

  1. Редактировать String_Insert_Launcher и поместить этот файл в директории с файлами, которые вы хотите изменить. ПРИМЕЧАНИЕ Настоятельно необходимо, чтобы этот файл находился в той же папке, что и ВСЕ остальные ваши файлы, которые вы хотите отредактировать. Вам необходимо отредактировать переменные в этом файле, чтобы соответствовать вы файловой batchpath

  2. Редактировать InsertString.bat и поместить этот файл в том же каталоге вы установите переменную batchpath выше Вам необходимо отредактировать переменные в этом файле в сопрягать файловую систему insertpath DestPath top_last_line insert_last_line bot_last_line

  3. Редактировать insert.txt и поместить этот файл в том же каталоге, установить insertpath выше Вам нужно поместите строки (строки), которые вы хотите вставить в свой файл внутри этого текстового документа.

  4. Проверьте свои журналы и убедитесь, что количество файлов в файле «Modified_Filelist.txt» (найдено в папке% insertpath%) так же, как и количество файлов, с которых вы начали.

Структура файлов:


* insert.txt *


В этом файле вы хотите поместить текст, который вы хотите вставить в файлы, которые вы будет нацелена. Причина использования отдельного файла заключается в том, что специальные символы (>, <, /, \, |, ^,% и т. Д.) Не обрабатываются как аргументы в пакетном файле. Этот файл должен находиться в том же месте, что и переменная, которую вы установите в InsertString.bat с именем «insertpath» или ссылаетесь в пакетном файле как% insertpath%.


* InsertString.bat *


В этом файле вы найдете переменные, которые должны быть установлены для работы сценария. Переменные включали:

  **1. filelist - This sets the counter for counting how many files were edited *this should not be edited* 
     **2. insertpath - This sets the path of insert.txt file containing the string you want to insert into the files that will be edited. If this location does not exist it will create it. 
     **3. destpath - This sets the path for the location of the files after they're edited. If this location does not exist it will create it. 
     **4. top_last_line - This sets the LAST GOOD LINE of the file that will be edited before the insert.txt is added. In essence this will split the file into 2 parts and add the contents of " insert.txt " into the middle of those 2 parts. 
     **5. insert_last_line - This sets the number of lines to add to the file from insert.txt (i.e. if insert_last_line=2 then the top two lines will be added after top_last_line) 
     **6. bot_last_line - This sets the last line of the original file (i.e. if there are 25 lines in the original file bot_last_line should be 25 - always over esitimate this, because if this number is less than the original not all lines will be rewritten to the new file) 

Этот файл должен быть в том же месте, что и переменная, которую установят в String_Insert_Launcher.bat под названием «batchpath» или ссылка в пакетном файле как% batchpath%.


* String_Insert_Launcher.bat *


Это скрипт, который вы будете выполнять, чтобы редактировать все файлы. Запустите этот пакетный скрипт из папки с файлами, которые вы хотите редактировать. Этот файл захватывает все имена файлов и запускает InsertString.bat во всех этих файлах. Внутри этого файла вы найдете varaible, который должен быть установлен для работы скрипта. Переменная включена: batchfilepath - Это местоположение фактического командного файла, который выполняет всю работу. Это местоположение JUST путь к файлу, не включая имена файлов.

ФАЙЛ # 1: String_Insert_Launcher.bat

@ECHO off 
TITLE Insert String to XML Script Launch File 
COLOR 02 

set batchfilepath=C:\JHA\Synergy\insertpath 
REM This is the location of the actual batch file that does all of the work. This location is JUST the filepath, not including any filenames. 
IF NOT exist %batchfilepath% md %batchfilepath% 
IF NOT exist %batchfilepath%\InsertString.bat goto pause 

:run 
for /f "delims=" %%f in ('dir /b /a-d-h-s') do "%batchfilepath%\InsertString.bat" %%f 
REM This command string gets the names of all of the files in the directory it's in and then runs the InsertString.bat file against every file individually. 

:pause 
cls 
echo.The file InsertString.bat is not in the correct directory. 
echo.Please put this file in the location listed below: 
echo. 
echo.------------------------- 
echo.%batchfilepath% 
echo.------------------------- 
echo. 
echo.When this file has been added press any key to continue running the script. 
pause 
goto run 

REM Insert String to XML Script 
REM Created by Trevor Giannetti 
REM An unpublished work 

ФАЙЛ # 2: Insert_String.bat

@ECHO off 
TITLE Insert String to XML Script 
COLOR 02 
SETLOCAL enabledelayedexpansion 

REM From Command Line:    for /f "delims=" %f in ('dir /b /a-d-h-s') do InsertString.bat %f 

REM --------------------------- 
REM *** EDIT VARIABLES BELOW *** 
REM --------------------------- 

set insertpath=C:\JHA\Synergy\insertpath 
REM This sets the path of insert.txt file containing the string you want to insert into the files that will be edited. If this location does not exist it will create it. 
set destpath=C:\JHA\Synergy\destination 
REM This sets the path for the location of the files after they're edited. If this location does not exist it will create it. 
set top_last_line=1 
REM This sets the LAST GOOD LINE of the file to be edited before the insert.txt is added. In essence this will split the file into 2 parts and add the contents of " insert.txt " into the middle of those 2 parts. 
set insert_last_line=1 
REM This sets the number of lines to add to the file from insert.txt (i.e. if insert_last_line=2 then the top two lines will be added after top_last_line) 
set bot_last_line=25 
REM This sets the last line of the original file (i.e. if there are 25 lines in the original file bot_last_line should be 25 - always over esitimate this, because if this number is less than the original not all lines will be rewritten to the new file) 

REM --------------------------- 
REM *** DO NOT EDIT BELOW *** 
REM --------------------------- 

set filelist=0 
REM This sets the counter for counting how many files were edited 
IF '%1'=='' goto usage 

IF NOT exist %insertpath% md %insertpath% 
IF NOT exist %destpath% md %destpath% 

:top_of_file 
IF EXIST %destpath%\%1 set done=T 
IF EXIST %destpath%\%1 goto exit 
IF '%1'=='InsertString.bat' goto exit 
IF '%1'=='insert.txt' goto exit 
IF '%1'=='Modified_Filelist.txt' goto exit 
IF '%1'=='String_Insert_Launcher.bat' goto exit 
set /a FirstLineNumber = 1 
REM This is the first line in the file that you want edited 
set /a LastLineNumber = %top_last_line% 
REM This is the last line in the file that you want edited 

SET /a counter=1 

for /f "usebackq delims=" %%a in (%1) do (
    if !counter! GTR !LastLineNumber! goto next 
    if !counter! GEQ !FirstLineNumber! echo %%a >> %destpath%\%1 
    set /a counter+=1 
) 

goto next 

:next 
REM echo TEXT TO BE INSERTED >> %destpath%\%1 
REM goto bottom_of_file 
REM The above can be substituted for the rest of :next if you don't have special characters in the text you need inserted 

set /a FirstLineNumber = 1 
REM This is the first line in the file with the text you need inserted in the file you want edited 
set /a LastLineNumber = %insert_last_line% 
REM This is the last line in the file with the text you need inserted in the file you want edited 

SET /a counter=1 
for /f "usebackq delims=" %%a in (%insertpath%\insert.txt) do (
    if !counter! GTR !LastLineNumber! goto next 
    if !counter! GEQ !FirstLineNumber! echo %%a >> %destpath%\%1 
    set /a counter+=1 
) 
REM The %insertpath%\insert.txt is the name of the file with the text you want inserted into the file you want edited 

goto bottom_of_file 

:bottom_of_file 
set /a FirstLineNumber = 1+%top_last_line% 
REM This is the first line in the second part of the file with the text you need inserted in the file you want edited 
set /a LastLineNumber = %bot_last_line% 
REM This is the last line in the second part of the file with the text you need inserted in the file you want edited 
REM The above is the split, after the top_of_file. The rest of the contents of the original file will be added after the text you want inserted is appended to the file 

SET /a counter=1 

for /f "usebackq delims=" %%a in (%1) do (
    if !counter! GTR !LastLineNumber! goto exit 
    if !counter! GEQ !FirstLineNumber! echo %%a >> %destpath%\%1 
    set /a counter+=1 
) 

goto logging 

:logging 
IF NOT EXIST %insertpath%\Modified_Filelist.txt echo Modified File List: > %insertpath%\Modified_Filelist.txt 
for /f "tokens=1 delims=[]" %%a in ('find /v /c "" ^< %insertpath%\Modified_Filelist.txt') do (
echo %%a - %1 >> %insertpath%\Modified_Filelist.txt 
) 

goto exit 

:usage 
cls 
echo Usage: InsertString.bat FILENAME 
echo You are missing the file name in your string 

:exit 
IF '%done%'=='T' echo %1 Already exists in folder! 
IF '%done%'=='T' echo Not modifying %1 
IF '%done%'=='T' echo Moving on to next file... 
IF EXIST %destpath%\InsertString.bat del %destpath%\InsertString.bat 
IF EXIST %destpath%\insert.txt del %destpath%\insert.txt 

REM Insert String to XML Script 
REM Created by Trevor Giannetti 
REM An unpublished work 

ФАЙЛ # 3: Insert.txt

<Vocabulary="Conv"> 

В вашем случае вы могли бы использовать 2 файла ... один с <value> и один с </value> (Я знаю, что это неряшливо, но он будет работать ...) Затем из моего командного скрипта InsertString.bat вы бы просто поставьте следующий цикл 2x (по одному для каждого из ваших файлов), а между ними вы будете помещать эхо.% userInputFromBeginningofBatch% >> Файл.xml

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

+1

+1, для этих усилий даже это бесполезно для командного файла, и есть некоторые ошибки со специальными символами, такими как восклицательные знаки будут удалены из файлов, одно место будет добавлено в каждой строке, а пустые строки будут удалены и не засчитаны , – jeb

+2

Это мой первый пост здесь, в StackOverflow, но я действительно получил эту работу без каких-либо проблем. Я заметил, что после строк вы получаете дополнительное пространство ... Мне нужно оглянуться на код и посмотреть, могу ли я избежать этого, однако у меня не было никаких проблем с загрузкой этого xml с пробелами. Что касается пустых строк, вы правы. Но конечный результат - это файлы, которые редактируются. Я никогда не говорил, что это будет красиво! Спасибо за +1 и за комментарии, не обращайте внимания на дополнительное пространство. – rud3y

2

Извините. Я заранее извиняюсь за этот пост. Я знаю, что это очень старая тема, но после прочтения ответов здесь я не мог удержаться от соблазна опубликовать этот ответ.

Обработка файла XML с помощью пакетной программы является не только простым и прямым, но по моему скромному мнению, легче, чем любое аналогичное решение в VBScript, PowerShell и т.д. Вот он:

@echo off 
setlocal EnableDelayedExpansion 
set "greater=>" 
set targetLine=Csetting name="BaseDirectory" serializeAs="String"!greater! 
echo Enter the new line to insert below target lines: 
set /P nextLine= 
setlocal DisableDelayedExpansion 

(for /F "delims=" %%a in (document.xml) do (
    set "line=%%a" 
    setlocal EnableDelayedExpansion 
    echo !line! 
    if "!line!" equ "!targetLine!" echo !nextLine! 
    endlocal 
)) > newDocument.xml 

Единственная проблема с предыдущей программой заключается в том, что она удаляет пустые строки из XML-файла, но эта деталь может быть исправлена ​​очень просто, добавив пару команд больше. Предыдущая программа может быть изменена, чтобы не проверять полную строку (как первоначально запрошено ОП), но проверьте три части таким же образом на примере последнего примера VBScript:

(for /F "delims=" %%a in (document.xml) do (
    set "line=%%a" 
    setlocal EnableDelayedExpansion 
    echo !line! 
    set lineMatch=1 
    if "!line:Csetting name=!" equ "!line!" set lineMatch= 
    if "!line:BaseDirectoy=!" equ "!line!" set lineMatch= 
    if "!line:serializeAs=!" equ "!line!" set lineMatch= 
    if defined lineMatch echo !nextLine! 
    endlocal 
)) > newDocument.xml 
Смежные вопросы