【问题标题】:Parsing xml to and replacing specific tags shell script将 xml 解析为并替换特定标签的 shell 脚本
【发布时间】:2017-10-13 12:36:24
【问题描述】:

对于下面的 xml,我需要将 <studentStatus> 替换为 <studentName>CLASSA</studentName><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 。仅适用于&lt;studentType&gt;Juniour&lt;/studentType&gt;。 我应该如何编辑 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 这样的工具,但不确定它是否安装在我们集群的所有节点中。

任何帮助将不胜感激。 提前致谢!

【问题讨论】:

  • "这可以使用 sed 来完成吗。" 请参阅:stackoverflow.com/a/1732454/3016153(同样适用于 XML)。
  • 你可以访问xmlstarlet吗?
  • 相当肯定python在大多数系统上都带有一个xml模块,可以试试。
  • 您的文件不是有效的 XML。至少缺少一个&lt;/student&gt;
  • @Cyrus 已编辑。我检查了 xmlstarlet。 xmlstarlet-bash: xmlstarlet: command not found

标签: bash shell xml-parsing xmlstarlet xmllint


【解决方案1】:

xmllint 更新file.xml 中的值:

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"))

【讨论】:

  • 如果我的xml在一个变量中,这个命令怎么修改?
  • 嗨@Cyrus,我尝试添加 xml=$(xmllint --shell
  • 嗨赛勒斯,对于看起来像 的 xml 标记,此命令不起作用。 xml=$(echo -e "cd /studentFile/student[studentName='CLASSA']/studentActions/st‌​udentAction[studentT‌​ype='Juniour']/stude‌​ntStatus\nset failed\nsave -" | xmllint -- shell /studentFile/student[studentName='CLASSA']/studentActions/st‌​udentAction[studentT‌​ype='Juniour']/stude‌​ntStatus is an empty Node Set,这个命令可以修改吗?任何帮助表示赞赏!
  • 很遗憾,我无法重现此内容。
  • 刚刚找到了一个解决方法,我将新的 xml 节点模式存储在一个变量中,使用 xmllint 更新它,然后通过 sed 替换它。感谢赛勒斯的帮助
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    如果xmlstarlet(用于查询/编辑/检查/转换的命令行工具包 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 - 编辑/更新模式

    //studentAction/studentStatus - 选择 studentStatus 元素的 xpath 表达式:

    • preceding-sibling::studentType[1][text() = 'Juniour'] - 前面的兄弟元素 studentType 具有值 Juniour
    • ancestor::student/studentName[text() = 'CLASSA'] - 最近的元素 studentName 与值 CLASSA

    【讨论】:

    • 不确定这个答案的重点,他们在 cmets 中说不是......
    • @123,这很可悲。在准备分析器时错过了该评论
    • 他们刚刚添加的评论看起来可能是一个有用的答案,所以不要太伤心
    • @123,可悲的是有人无法安装这些有用的工具
    【解决方案4】:

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

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

    Xembly 的完整语法是here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多