我正在尝试编辑/更新一些复杂的XML,遗憾的是我无法更改格式。我在Bash脚本中使用XMLStarlet。
我在苦苦挣扎的时候,就是当我尝试检索或编辑属性"name={name}"
不唯一的属性的CDATA值并返回多个值时。
例如,我有以下XML:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="key.xsl" ?>
<tables>
<tableset>
<table name="table1">
<row>
<fld name="fileName">
<strval><![CDATA[/my/XYZ/file1]]></strval>
</fld>
<fld name="fileName">
<strval><![CDATA[/my/XYZ/file2]]></strval>
</fld>
<fld name="fileName">
<strval><![CDATA[/my/other/XYZ/file3]]></strval>
</fld>
<fld name="worksBecauseUnique">
<strval><![CDATA[/XYZ/unique]]></strval>
</fld>
</row>
</table>
</tableset>
</tables>
使用XMLStarlet时,我可以轻松编辑以下值:
xmlstarlet ed -L \
-u '//tables/tableset/table/row/fld[@name="worksBecauseUnique"]/strval/text()' \
-v '/ABC/unique' \
myxmlfile.xml
但是,在尝试使用属性name=fileName
修改任何CDATA值时,我遇到了问题,因为fileName
在XML中出现不止一次。
我希望输出如下:
<fld name="fileName">
<strval><![CDATA[/my/ABC/file1]]></strval>
</fld>
<fld name="fileName">
<strval><![CDATA[/my/ABC/file2]]></strval>
</fld>
<fld name="fileName">
<strval><![CDATA[/my/other/ABC/file3]]></strval>
</fld>
问题是,如果我尝试使用XMLStarlet更新fileName
的CDATA值,如何在不更新所有内容的情况下更新每个值?
例如,如果我跑:
xmlstarlet ed -L \
-u "//tables/tableset/table/row/fld[@name=\"fileName\"]/strval/text()" \
-v "/my/ABC/file1" \
myxmlfile.xml
我得到以下不正确的输出:
<fld name="fileName">
<strval><![CDATA[/my/ABC/file1]]></strval>
</fld>
<fld name="fileName">
<strval><![CDATA[/my/ABC/file1]]></strval>
</fld>
<fld name="fileName">
<strval><![CDATA[/my/ABC/file1]]></strval>
</fld>
注意每个CDATA值如何设置为"/my/ABC/file1"
我需要"/my/ABC/file1"
,"/my/ABC/file2"
和"/my/other/ABC/file3"
我希望以某种方式允许某人单独修改每个值... 希望使用任何支持XPath的工具都可以实现这一点。
非常感谢任何帮助!
答案 0 :(得分:1)
提供一个表达式(带-x
),将输入修改为您想要的输出:
xmlstarlet ed \
-u '//fld/strval[contains(., "/XYZ/")]' \
-x 'concat(substring-before(., "/XYZ/"), "/ABC/", substring-after(., "/XYZ/"))'
<in.xml >out.xml
顺便提一下,在较新版本的XPath标准中有更好的字符串替换功能;因为libxml(由XMLStarlet使用)仅支持1.0版本,所以表达式有点不像其他情况那样笨拙。