Я пытаюсь сгенерировать .txt отчет на основе .xml файлов для установленных библиотек. Должен сообщить номер библиотеки SNPID |Название библиотеки |Ключ реестра |Путь к библиотеке. Сортировка по возрастанию и, наконец, выравнивание столбцов.
Основная проблема заключается в том, что скрипт работает, когда в файле .xml есть только один SNPID и одно имя, но не в том случае, если в файле XML есть несколько SNPID и имен
Некоторые советы:
- Найденные строки / строки в файлах .xml ВСЕГДА имеют добавляющие пробелы
- SNPID также может содержать буквы.
- Внутри
<producthint>
</producthint>
у нас может быть несколько <product>
- Внутри
<product>
</product>
у нас может быть несколько <flavour>
</flavour>
- . порядок всегда одинаковый, имя 1-е:
<Name></Name>
<SNPID></SNPID>
- Но имя / SNPID может быть либо внутри
<product>
</product>
, либо внутри <flavour>
</flavour>
- Когда в
<product>
есть значение <flavour>
, RegKey продукта одинаков для всех разновидностей.
Вот мой код ...
@echo off
pushd "%~dp0"
setlocal
set "Backup_Folder=%~dp0NI_Backup"
set "SNPID_List=%Backup_Folder%\SNPID_Report.txt"
set "SNPID_TMP_List_To_Order=%Backup_Folder%\SNPID_TMP_List_To_Order.txt"
set "SNPID_TMP_List_To_Realign=%Backup_Folder%\SNPID_TMP_List_To_Realign.txt"
set "XML_Dir=C:\Program Files\Common Files\Native Instruments\Service Center"
set "Registry_Key=HKLM\SOFTWARE\Native Instruments"
if not exist "%Backup_Folder%" ( mkdir "%Backup_Folder%" >nul 2>&1 )
setlocal EnableDelayedExpansion
REM Loop through .xml
(
for /f "delims=" %%a in ('dir /s/b/a-d "%XML_Dir%\*.xml"^| find /v "NativeAccess" ^| find /v "ProductHints" ^| find /v "Maschine 2"') do (
for /f "usebackqtokens=1-3delims=<>" %%E in ("%%a") do (
if "%%F"=="SNPID" (
for /f "usebackqtokens=1-3delims=<>" %%I in ("%%a") do (
if "%%J"=="Name" (
for /f "usebackqtokens=1-3delims=<>" %%M in ("%%a") do (
if "%%N"=="RegKey" (
for /f "tokens=2*" %%Q in ('reg query "%Registry_Key%\%%O" /v "ContentDir" 2^>nul ') do (
set "ContentDir=%%R"
if "!ContentDir:~1,2!"==":\" ( echo %%G ^| %%K ^| %Registry_Key%\%%O ^| %%R )
))))))))
)>"%SNPID_TMP_List_To_Order%"
REM Rename Paths ending with backslash
call "%~dp0Jrepl.bat" "(.*)\\$" "$1" /xseq /m /f "%SNPID_TMP_List_To_Order%" /o -
REM Remove duplicates
call "%~dp0Jrepl.bat" "\c([\c\r\n]+)\r?\n(?=[\s\S]*\c\1$)" "" /xseq /m /f "%SNPID_TMP_List_To_Order%" /o -
REM echo column title
echo SNPID^| Library Name^| Registry Key^| Library Location>"%SNPID_TMP_List_To_Realign%"
REM Sort by SNPID number
sort <"%SNPID_TMP_List_To_Order%" >>"%SNPID_TMP_List_To_Realign%"
REM Get Columns length
set "SNPID_MaxLength=0"
set "LibName_MaxLength=0"
set "RegKey_MaxLength=0"
for /f "usebackqtokens=1-3 delims=|" %%a in ("%SNPID_TMP_List_To_Realign%") do (
set "String=%%a" & call :strlen
for /f "tokens=* delims=0" %%B in ("!result!") do (
if %%B gtr !SNPID_MaxLength! set "SNPID_MaxLength=%%B"
)
set "String=%%b" & call :strlen
for /f "tokens=* delims=0" %%B in ("!result!") do (
if %%B gtr !LibName_MaxLength! set "LibName_MaxLength=%%B"
)
set "String=%%c" & call :strlen
for /f "tokens=* delims=0" %%B in ("!result!") do (
if %%B gtr !RegKey_MaxLength! set "RegKey_MaxLength=%%B"
)
)
REM Set Columns Spacing
set "Space_Count=%SNPID_MaxLength%"
set "SNPID_Space= "
set "LibName_Space= "
set "RegKey_Space= "
:SNPID_Spacing
if "%Space_Count%"=="0" ( set "Space_Count=%LibName_MaxLength%" & goto :LibName_Spacing )
set "SNPID_Space=%SNPID_Space% "
set /a "Space_Count-=1"
goto :SNPID_Spacing
:LibName_Spacing
if "%Space_Count%"=="0" ( set "Space_Count=%RegKey_MaxLength%" & goto :RegKey_Spacing )
set "LibName_Space=%LibName_Space% "
set /a "Space_Count-=1"
goto :LibName_Spacing
:RegKey_Spacing
if "%Space_Count%"=="0" ( goto :Realign_Columns )
set "RegKey_Space=%RegKey_Space% "
set /a "Space_Count-=1"
goto :RegKey_Spacing
REM Columns Alignment
:Realign_Columns
(
for /f "usebackqtokens=1-4 delims=|" %%a in ("%SNPID_TMP_List_To_Realign%") do (
set "SNPID_Aligned=%%a%SNPID_Space%" & set "SNPID_Aligned=!SNPID_Aligned:~0,%SNPID_MaxLength%!"
set "LibName_Aligned=%%b%LibName_Space%" & set "LibName_Aligned=!LibName_Aligned:~0,%LibName_MaxLength%!"
set "RegKey_Aligned=%%c%RegKey_Space%" & set "RegKey_Aligned=!RegKey_Aligned:~0,%RegKey_MaxLength%!"
echo !SNPID_Aligned!^|!LibName_Aligned!^|!RegKey_Aligned!^|%%d
)
)>"%SNPID_List%"
endlocal
REM del "%SNPID_TMP_List%" "%SNPID_TMP_List_To_Order%" "%SNPID_TMP_List_To_Realign%"
pause & exit /b
:strlen
(
(set^ tmp=!String!)
set "len=1"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!tmp:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "tmp=!tmp:~%%P!"
))
)
(
set "result=!len!"
exit /b
)
(я упростилXML-файлы здесь)
<?xml version="1.0" encoding="UTF-8"?>
<ProductHints>
<Product version="3">
<Name>Battery 4</Name>
<Company>Company Name</Company>
<some value>xxx</some value>
<RegKey>Battery</RegKey>
<some value>yyy</some value>
<BingName>Battery 4</BingName>
<SNPID>249</SNPID>
</Product>
</ProductHints>
даст:
249 | Battery 4 | Battery | PATH
, в то время как
<?xml version="1.0" encoding="UTF-8"?>
<ProductHints>
<Product version="3">
<Name>Maschine 2</Name>
<Company>Company Name</Company>
<SNPID>334165166167</SNPID>
<RegKey>Maschine 2</RegKey>
<Flavour>
<Name>Maschine 2</Name>
<SNPID>334</SNPID>
<Value>0</Value>
</Flavour>
<Flavour>
<Name>Maschine 2 Essentials</Name>
<Value>-1</Value>
<SNPID>165</SNPID>
</Flavour>
<Flavour>
<Name>Another Flavour</Name>
<SNPID>166</SNPID>
<some value>yyy</some value>
</Flavour>
<Flavour>
<Name>Another Flavour2</Name>
<some value>yyy</some value>
<SNPID>167</SNPID>
</Flavour>
</Product>
<Product version="3">
<Name>Battery 4</Name>
<Company>Company Name</Company>
<some value>xxx</some value>
<RegKey>Battery</RegKey>
<some value>yyy</some value>
<BingName>Battery 4</BingName>
<SNPID>249</SNPID>
</Product>
</ProductHints>
даст:
165 | Maschine 2
166 | Maschine 2
167 | Maschine 2
334 | Maschine 2
249 | Maschine 2
165 | Maschine 2 Essentials
166 | Maschine 2 Essentials
167 | Maschine 2 Essentials
334 | Maschine 2 Essentials
249 | Maschine 2 Essentials
165 | Another Flavour
166 | Another Flavour
167 | Another Flavour
334 | Another Flavour
249 | Another Flavour
etc...
, нодолжно быть только:
165 | Maschine 2
334 | Maschine 2 Essentials
249 | Battery 4
166 | Another Flavour
167 | Another Flavour2
optionally, also
334165166167| Maschine 2
or without... (would like to see both outputs)
Значение:
Всегда ассоциируйте SNPID с его ИМЯ внутри <Product>
</Product>
, если только внутри <Product></Product>
нет значения <flavour>
, тогда я ассоциируюSNPID с ИМЯ, которое находится внутри <flavour>
</flavour>
.
Пропуск первого ИМЯ в случае, если есть вкус, или нет ... Мне нужно было бы посмотреть два разных проанализированных вывода, чтобы выбрать.
NAME всегда выше своего номера SNPIDно между ними может быть несколько значений (и разное количество строк)
Когда присутствует значение ароматизатора, аромат RegKey равен Product Regkey
Обновление: обновлен вопрос с попыткой синтаксического анализа PS, это работает хорошо, но я не могу решить "вещь вкуса", слишком сложно для меня ... также не могу вывести в UTF8NOBOM
"DummyLine" | Out-File "$PSScriptRoot\Parsed_List.txt" -Encoding UTF8
$items = Get-ChildItem "C:\Program Files\Common Files\Native Instruments\Service Center\*.xml"
foreach ($item in $items) {
[xml]$XML_File = Get-Content $item
$XML_File.ProductHints.Product | % {
$Name = $_.Name
$RegKey = $_.RegKey
If (-Not $_.SNPID) {$SNPID = "ThirdParty"} Else {$SNPID = $_.SNPID}
If (-Not $_.Company) {$Company = "Not specified"} Else {$Company = $_.Company}
If ($SNPID -eq "334165") {$Name = "Maschine 2 Essential";$SNPID = "165"}
"$SNPID`|$Name`|$Company`|$RegKey`|Location" | Out-File "$PSScriptRoot\Parsed_List.txt" -append -Encoding UTF8
}
}