XMLStarlet - 替换属性的一部分

时间:2014-11-19 22:54:02

标签: xml batch-file xpath cmd xmlstarlet

我正在使用XMLStartlet为我的应用程序快速部署cmd(Windows)脚本,我正在更改配置xml文件。

操作整个节点/属性非常完美,但我需要用特定值替换属性的一部分,例如:

<list>
    <address id="a1">
        <data url="http://localhost:8000/a1.html" />
    </address>
    <address id="a2">
        <data url="http://localhost:8000/a2.html" />
    </address>
</list>

我需要更改/list/address/data/@url的端口部分才能获得:

<list>
    <address id="a1">
        <data url="http://localhost:8001/a1.html" />
    </address>
    <address id="a2">
        <data url="http://localhost:8001/a2.html" />
    </address>
</list>

非常感谢任何有关xmlstarlet命令的帮助。我不想把sed混合到我的脚本中。

2 个答案:

答案 0 :(得分:1)

使用XPath string functionsconcatsubstring-after

xmlstarlet ed -u /list/address/data/@url ^
  -x "concat('http://localhost:8001/', substring-after(substring-after(., 'http://localhost:'), '/'))" ^
  addr-list.xml > new-addr-list.xml
move new-addr-list.xml addr-list.xml

您可以修改--inplace而不是move

xmlstarlet ed --inplace -u /list/address/data/@url ^
  -x "concat('http://localhost:8001/', substring-after(substring-after(., 'http://localhost:'), '/'))" ^
  addr-list.xml

答案 1 :(得分:0)

对于batch + xmlstarlet解决方案

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "count=1"

    rem For each url in the xml file
    for /f "delims=" %%v in ('
        xml sel -t -v "/list/address/data/@url" input.xml
    ') do (

        rem Split the line using colons as delimiters
        rem So we have %%a = http    %%b = //localhost    %%c = 8001/....
        for /f "tokens=1,2,* delims=:" %%a in ("%%v") do (

            rem Remove the port number from %%c using the numbers as delimiters
            for /f "tokens=* delims=0123456789" %%d in ("%%c") do (

                rem Here we have all the needed elements. Retrieve the number of the 
                rem element being updated (with delayed expansion) and update the 
                rem xml document (without delayed expansion to avoid problems)
                setlocal enabledelayedexpansion
                for %%n in (!count!) do ( 
                    endlocal
                    xml edit -L -u "/list/address[%%n]/data/@url" -v "%%a:%%b:8003%%d" input.xml
                )
            )
        )
        rem This instance has been processed. Increment counter
        set /a "count+=1"
    )