将 xml 解析为并替换特定标签 shell 脚本

Parsing xml to and replacing specific tags shell script

对于下面的 xml ,我需要将 <studentName>CLASSA</studentName><studentStatus> 替换为 <studentStatus>failed</studentStatus>.

<studentFile>
    <student>
        <studentName>CLASSA</studentName>
        <studentStatus>Success</studentStatus>
        <studentActions>
            <studentAction>
                <studentType>Juniour</studentType>
                <studentStatus>Completed</studentStatus>
                <studentMsg/>
            </studentAction>
            <studentAction>
                <studentType>HighSchool</studentType>
                <studentStatus>Completed</studentStatus>
                <studentMsg/>
            </studentAction>
        </studentActions>
    </student>
    <student>
        <studentName>CLASSB</studentName>
        <studentStatus>Success</studentStatus>
        <studentActions>
            <studentAction>
                <studentType>Senior</studentType>
                <studentStatus>Completed</studentStatus>
            </studentAction>
            <studentAction>
                <studentType>Middle</studentType>
                <studentStatus>Completed</studentStatus>
            </studentAction>                         
        </studentActions>
    </student>
</studentFile>

到目前为止我得到了什么,

xmllint -xpath "/studentFile/student[studentName='CLASSA']/studentActions/studentAction[studentType="Juniour"]/studentStatus" myxml.xml

现在我得到学生的状态为 Completed ,现在这个值应该更改为 Failed 。仅限 <studentType>Juniour</studentType>。 我应该如何编辑 xml 才能将其设为 ,

<studentFile>
    <student>
        <studentName>CLASSA</studentName>
        <studentStatus>Success</studentStatus>
        <studentActions>
            <studentAction>
                <studentType>Juniour</studentType>
                <studentStatus>Failed</studentStatus>
                <studentMsg/>
            </studentAction>
            <studentAction>
                <studentType>HighSchool</studentType>
                <studentStatus>Completed</studentStatus>
                <studentMsg/>
            </studentAction>
        </studentActions>
    </student>
    <student>
        <studentName>CLASSB</studentName>
        <studentStatus>Success</studentStatus>
        <studentActions>
            <studentAction>
                <studentType>Senior</studentType>
                <studentStatus>Completed</studentStatus>
            </studentAction>
            <studentAction>
                <studentType>Middle</studentType>
                <studentStatus>Completed</studentStatus>
            </studentAction>                         
        </studentActions>
    </student>
</studentFile>

这可以使用 sed 来完成吗?我知道有像 xsltproc 这样的工具,但不确定它是否安装在我们集群的所有节点中。

如有任何帮助,我们将不胜感激。 提前致谢!

如果 xmlstarlet(query/edit/check/transform 的命令行工具包 XML 个文档)可访问:

xmlstarlet ed -u "//studentAction/studentStatus[preceding-sibling::studentType[1][text() = 'Juniour'] \
           and ancestor::student/studentName[text() = 'CLASSA']]" -v failed students.xml

以上将输出需要替换的初始 XML 文档


命令详情:

ed -u - edit/update 模式

//studentAction/studentStatus - select studentStatus 元素的 xpath 表达式具有:

  • preceding-sibling::studentType[1][text() = 'Juniour'] - 在同级元素 studentType 之前的值为 Juniour
  • ancestor::student/studentName[text() = 'CLASSA'] - 最近的元素 studentName,值为 CLASSA

xlmlint,顾名思义,是为了解析和验证XML,而不是编辑它。如果您可以在集群上安装 xmlstarlet,则可以执行以下操作:

xmlstarlet ed --update "/studentFile/student[studentName='CLASSA']/studentActions/studentAction[studentType='Juniour']/studentStatus" --value "Failed" *file*

file.xml 中使用 xmllint 更新值:

xmllint --shell file.xml << EOF
cd /studentFile/student[studentName='CLASSA']/studentActions/studentAction[studentType='Juniour']/studentStatus
set failed
save
EOF

或没有here document:

echo -e "cd /studentFile/student[studentName='CLASSA']/studentActions/studentAction[studentType='Juniour']/studentStatus\nset failed\nsave" | xmllint --shell file.xml

更新:在变量中使用 bash 和 XML:

xml=$(xmllint --shell <(echo "$xml") << EOF
cd /studentFile/student[studentName='CLASSA']/studentActions/studentAction[studentType='Juniour']/studentStatus
set failed
save -
EOF
)

或没有此处文档:

xml=$(echo -e "cd /studentFile/student[studentName='CLASSA']/studentActions/studentAction[studentType='Juniour']/studentStatus\nset failed\nsave -" | xmllint --shell <(echo "$xml"))

您可以试试我的 Xembly 命令行工具:

$ xembly --xml file.xml 'XPATH "/studentFile/student[studentName=\'CLASSA\']/studentActions/studentAction[studentType=\'Juniour\']/studentStatus"; SET "failed";'

Xembly 的完整语法是 here