我正在尝试使用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处理器。这两个参数都使用您的默认值初始化。