Изменить повторяющееся слово / текст в XML на основе соответствующего текста / параметров? - PullRequest
1 голос
/ 22 мая 2019

У меня есть XML-файл, содержащий следующее:

  <SubtitleTracks>
    <SubtitleTrack>
      <IsNotifying>true</IsNotifying>
      <Burned>false</Burned>
      <Default>false</Default>
      <Forced>false</Forced>
      <SourceTrack>
        <SourceId>0</SourceId>
        <TrackNumber>1</TrackNumber>
        <Language>English [VOBSUB]</Language>
        <LanguageCode>eng</LanguageCode>
        <SubtitleType>VobSub</SubtitleType>
      </SourceTrack>
      <SrtOffset>0</SrtOffset>
      <SubtitleType>VobSub</SubtitleType>
    </SubtitleTrack>
    <SubtitleTrack>
      <IsNotifying>true</IsNotifying>
      <Burned>false</Burned>
      <Default>false</Default>
      <Forced>false</Forced>
      <SourceTrack>
        <SourceId>0</SourceId>
        <TrackNumber>2</TrackNumber>
        <Language>English [VOBSUB]</Language>
        <LanguageCode>eng</LanguageCode>
        <SubtitleType>VobSub</SubtitleType>
      </SourceTrack>
      <SrtOffset>0</SrtOffset>
      <SubtitleType>VobSub</SubtitleType>
    </SubtitleTrack>
  </SubtitleTracks>

Раздел <SubtitleTrack> может повторяться несколько раз по всему файлу.

Однако структура всегда одинакова.Единственное, что изменяется в этом разделе, это:

<SourceId>0</SourceId>
<TrackNumber>1</TrackNumber>

, тогда следующий будет:

<SourceId>0</SourceId>
<TrackNumber>2</TrackNumber>

и так далее ...

Прямо сейчас, <Default>false</Default> всегда так.

Я хотел бы изменить <Default>false</Default> на <Default>true</Default> только , если SourceId равен 0 и TrackNumber равен 1 .

Может кто-нибудь помочь с переводом этих требований в пакетный файл?

РЕДАКТИРОВАТЬ: я думаю, что почти получил это, но эточто-то задыхается, в результате я продолжаю получать <Default>false</Default> false

@ECHO OFF
SETLOCAL
SET "sourcedir=C:\Test"
SET "destdir=C:\Test"
SET "filename1=%sourcedir%\TestOutput.txt"
SET "outfile=%destdir%\TestOutputFixed.txt"
SET "hotsection="
CALL :clear$

(
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
 rem if line contains `<SubtitleTrack>` we've entered hot section
 ECHO "%%a"|FIND "<SubtitleTrack>">NUL
 IF NOT ERRORLEVEL 1 SET "hotsection=y"
 SET "saved="
 IF DEFINED hotsection (
  FOR /L %%r IN (100,1,999) DO IF NOT DEFINED saved IF NOT DEFINED $%%r SET "$%%r=%%a"&SET "saved=Y"
  rem if line contains `</SubtitleTrack>` or `</SubtitleTracks>` then end-of-hotsection
  SET "endhot="
  SET "endtrack="
  FOR /f "tokens=1delims= " %%w IN ("%%a") DO FOR %%x IN ("</SubtitleTrack>") DO IF "%%w"==%%x SET "endhot=Y"&IF 

"</SubtitleTracks>"==%%x SET "endtrack=Y"
  IF DEFINED endhot (
   rem end-of-hotsection
   rem check whether we have SourceID 0 and TrackNumber 1
   SET "id0="&SET "track1="
   FOR /f "tokens=1,*delims== " %%r IN ('SET $') DO (
    IF "%%s"==""<SourceId>0" SET "id0=Y" 
    IF "%%s"==""<TrackNumber>1" SET "track1=Y" 
   )
   rem found end-of-hotsection. now regurgitate saved lines and set `default` appropriately
   FOR /f "tokens=2delims==" %%r IN ('SET $') DO (
    echo "%%r"|FINDSTR /r /c:" *\<Default>" >NUL
    IF ERRORLEVEL 1 (ECHO %%r) ELSE (
     FOR /f "tokens=1delims=:" %%s IN ("%%r") DO (
      IF defined track1 (IF DEFINED id0 (ECHO %%s true,) ELSE (ECHO %%s false,)) ELSE (ECHO %%s false,)
     )
    )
    CALL :clear$
    IF DEFINED endtrack SET "hotsection="
   )
  )
 ) ELSE (ECHO %%a)
)
)>"%outfile%"

GOTO :EOF

:clear$
:: remove variables starting $
FOR  /F "delims==" %%z In ('set $ 2^>Nul') DO SET "%%z="
GOTO :EOF

Ответы [ 2 ]

2 голосов
/ 22 мая 2019

Входной XML-файл:

$ cat subtitletracks.xml 
  <SubtitleTracks>
    <SubtitleTrack>
      <IsNotifying>true</IsNotifying>
      <Burned>false</Burned>
      <Default>false</Default>
      <Forced>false</Forced>
      <SourceTrack>
        <SourceId>0</SourceId>
        <TrackNumber>1</TrackNumber>
        <Language>English [VOBSUB]</Language>
        <LanguageCode>eng</LanguageCode>
        <SubtitleType>VobSub</SubtitleType>
      </SourceTrack>
      <SrtOffset>0</SrtOffset>
      <SubtitleType>VobSub</SubtitleType>
    </SubtitleTrack>
    <SubtitleTrack>
      <IsNotifying>true</IsNotifying>
      <Burned>false</Burned>
      <Default>false</Default>
      <Forced>false</Forced>
      <SourceTrack>
        <SourceId>0</SourceId>
        <TrackNumber>2</TrackNumber>
        <Language>English [VOBSUB]</Language>
        <LanguageCode>eng</LanguageCode>
        <SubtitleType>VobSub</SubtitleType>
      </SourceTrack>
      <SrtOffset>0</SrtOffset>
      <SubtitleType>VobSub</SubtitleType>
    </SubtitleTrack>
  </SubtitleTracks>

Лист преобразования:

$ cat subtitletransform.xslt 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  >

    <!-- copy all nodes and attributes -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- when find a default node for which the SourceId = 0 and trackNumber = 1 -->
    <xsl:template match="//SubtitleTrack/Default[../SourceTrack/SourceId = '0' and ../SourceTrack/TrackNumber = '1']">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <!-- assign value to true -->
            <xsl:value-of select="'true'"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Вывод:

$ xsltproc subtitletransform.xslt subtitletracks.xml 
<?xml version="1.0"?>
<SubtitleTracks>
    <SubtitleTrack>
      <IsNotifying>true</IsNotifying>
      <Burned>false</Burned>
      <Default>true</Default>
      <Forced>false</Forced>
      <SourceTrack>
        <SourceId>0</SourceId>
        <TrackNumber>1</TrackNumber>
        <Language>English [VOBSUB]</Language>
        <LanguageCode>eng</LanguageCode>
        <SubtitleType>VobSub</SubtitleType>
      </SourceTrack>
      <SrtOffset>0</SrtOffset>
      <SubtitleType>VobSub</SubtitleType>
    </SubtitleTrack>
    <SubtitleTrack>
      <IsNotifying>true</IsNotifying>
      <Burned>false</Burned>
      <Default>false</Default>
      <Forced>false</Forced>
      <SourceTrack>
        <SourceId>0</SourceId>
        <TrackNumber>2</TrackNumber>
        <Language>English [VOBSUB]</Language>
        <LanguageCode>eng</LanguageCode>
        <SubtitleType>VobSub</SubtitleType>
      </SourceTrack>
      <SrtOffset>0</SrtOffset>
      <SubtitleType>VobSub</SubtitleType>
    </SubtitleTrack>
  </SubtitleTracks>

Примечания:

В Windows для запуска процессора XSLT через командную строку посмотрите: Существуют ли какие-либо инструменты командной строки обработки XSLT?

1 голос
/ 22 мая 2019

Ваше ограничение для реализации с помощью пакетного файла CMD увеличивает сложность и снижает производительность.

Пакетные файлы используются для интеграции и синхронизации выполнения программы.

Ваша задача больше связана с обработкой текста / XMLprogram.

Более подходящим инструментом будут perl / python / awk scripts.Эти языки предназначены для обработки текста.

Вот пример 6-строчной программы awk:

awk '
pass1 && /<Default>false<\/Default>/ {markedLine = NR} 
pass1 && /<SourceId>0<\/SourceId>/ {sourceIdFlag = 1; next}
pass1 && sourceIdFlag && /<TrackNumber>1<\/TrackNumber>/ {markedLinesArr[markedLine] = 1}
pass1 {sourceIdFlag = 0}
!pass1 && markedLinesArr[FNR] == 1 {print "      <Default>true</Default>";next}
!pass1 {print}
' pass1=1 input.xml pass1=0 input.xml

Вывод

  <SubtitleTracks>
    <SubtitleTrack>
      <IsNotifying>true</IsNotifying>
      <Burned>false</Burned>
      <Default>true</Default>
      <Forced>false</Forced>
      <SourceTrack>
        <SourceId>0</SourceId>
        <TrackNumber>1</TrackNumber>
        <Language>English [VOBSUB]</Language>
        <LanguageCode>eng</LanguageCode>
        <SubtitleType>VobSub</SubtitleType>
      </SourceTrack>
      <SrtOffset>0</SrtOffset>
      <SubtitleType>VobSub</SubtitleType>
    </SubtitleTrack>
    <SubtitleTrack>
      <IsNotifying>true</IsNotifying>
      <Burned>false</Burned>
      <Default>false</Default>
      <Forced>false</Forced>
      <SourceTrack>
        <SourceId>0</SourceId>
        <TrackNumber>2</TrackNumber>
        <Language>English [VOBSUB]</Language>
        <LanguageCode>eng</LanguageCode>
        <SubtitleType>VobSub</SubtitleType>
      </SourceTrack>
      <SrtOffset>0</SrtOffset>
      <SubtitleType>VobSub</SubtitleType>
    </SubtitleTrack>
  </SubtitleTracks>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...