我正在尝试使用xmlstarlet更新具有相同模式的所有节点。给定以下xml
<root>
<application>
<provider name="alpha" value="my.corp.lion" />
<provider name="beta" value="my.corp.tiger" />
<provider name="gamma" value="my.corp.monkey" />
</application>
</root>
我目前可以如下更新每个节点
oldCorp="my.corp"
newCorp="new.my.corp"
myNode="/root/application/provider[@name='alpha']/@value"
oldValue=$(xml sel -t -v ${myNode} MyXml.xml)
newValue=${oldValue//$oldCorp/$newCorp}
xml ed --inplace -u ${myNode} -v "${newValue}" MyXml.xml
# results in provider.alpha being new.my.corp.lion
但是,我想对所有提供者节点进行操作,并将最终的xml结果更新为
<root>
<application>
<provider name="alpha" value="new.my.corp.lion" />
<provider name="beta" value="new.my.corp.tiger" />
<provider name="gamma" value="new.my.corp.monkey" />
</application>
</root>
是否有办法在providers
上进行foreach并将所有my.corp
实例替换为new.my.corp
?
-x
选项,如下所示:xmlstarlet ed --inplace -u "/root/application/provider/@value" -x "concat('new.my.corp',substring-after(.,'my.corp'))" input.xml
在您的特殊情况下,将代码更改为
oldCorp="my.corp" newCorp="new.my.corp" myNode="/root/application/provider/@value" xml ed --inplace -u "${myNode}" -x "concat('${newCorp}',substring-after(.,'${oldCorp}'))" MyXml.xml
输出是所需的:
<?xml version="1.0"?> <root> <application> <provider name="alpha" value="new.my.corp.lion"/> <provider name="beta" value="new.my.corp.tiger"/> <provider name="gamma" value="new.my.corp.monkey"/> </application> </root>
此代码将myNode
XPath指定的所有属性值替换为xmlstarlet的-x
参数中构造的值。[AFAIK xmlstarlet不支持RegEx,因此您必须使用XPath-1.0函数(例如
substring-after(...)
,substring(...)
等)创建替换表达式。
如果您需要RegEx进行替换,则必须使用XPath-2.0功能,该功能是XSLT-2.0的一部分。然后,您可以使用XSLT-2.0样式表(如下所示)实现相同的功能,但使用RegEx's:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="UTF-8" indent="yes"/> <xsl:param name="oldCorp" select="'my\.corp'" /> <xsl:param name="newCorp" select="'new.my.corp'" /> <!-- Identity template --> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*" /> </xsl:copy> </xsl:template> <xsl:template match="provider"> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:attribute name="value"> <xsl:value-of select="replace(@value,$oldCorp,$newCorp)" /> </xsl:attribute> </xsl:copy> </xsl:template> </xsl:stylesheet>
您可以将参数作为字符串传递给XSLT-2.0处理器。这两个参数都使用您的默认值初始化。