xmlstarlet foreach节点更新值

问题描述 投票:0回答:1

我正在尝试使用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

xml replace xmlstarlet
1个回答
0
投票
通常,使用xmlstarlet的-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处理器。这两个参数都使用您的默认值初始化。
© www.soinside.com 2019 - 2024. All rights reserved.