我有一个带有 xml 内容的 Heredoc,我添加了另一个文件的内容,如下所示:
bar
文件:
<bar>
$baz
</bar>
剧本:
bar=$(cat bar.xml)
# this would be the ideal, of course it doesn't work
baz=$(cat baz.xml)
#
cat << EOF > out.xml
<foo>
$bar
</foo>
EOF
的输出out.xml
:
<foo>
<bar>
$baz
</bar>
</foo>
现在我想将第三个文件添加到以下内容中bar
:
baz
文件:
<baz>baz<baz>
所以最终的内容out.xml
是:
<foo>
<bar>
<baz>baz</baz>
</bar>
</foo>
该工作流程假设我可以将(一个大的)xml 文件剥离为组件,每个组件都有自己的组件。
master (heredoc) xml
^^^
second xml
^^^
third xml
我不知道从哪里开始,因为我想让它尽可能简单,所以任何帮助表示赞赏。
答案1
组合 XML 文档的惯用方法是使用XSLT。首先,一些设置:
$ cd "$(mktemp --directory)"
$ echo '<foo/>' > ./foo.xml
$ echo '<bar/>' > ./bar.xml
$ echo '<baz/>' > ./baz.xml
然后我们创建一个 XSLT 文件,它将一个文件的内容插入到源文件中的一个元素中,并按原样复制文件的其余部分:
$ cat > ./insert.xslt <<'EOF'
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
> <xsl:template match="@* | node()">
> <xsl:copy>
> <xsl:apply-templates select="@* | node()"/>
> <xsl:if test="name() = $element">
> <xsl:copy-of select="document($file)"/>
> </xsl:if>
> </xsl:copy>
> </xsl:template>
> </xsl:stylesheet>
> EOF
现在我们可以将任意文件插入到另一个文件中:
$ xsltproc --output ./bar-insert.xml --stringparam file ./baz.xml --stringparam element bar ./insert.xslt ./bar.xml
$ cat ./bar-insert.xml
<?xml version="1.0"?>
<bar><baz/></bar>
让我们重复创建最终文件:
$ xsltproc --output ./foo-insert.xml --stringparam file ./bar-insert.xml --stringparam element foo ./insert.xslt ./foo.xml
$ cat ./foo-insert.xml
<?xml version="1.0"?>
<foo><bar><baz/></bar></foo>
这样做的好处是它可以处理任何 XML 文件,无论它们是否缩进,是否折叠空元素,等等。
如果多次引用该文件,它甚至会多次插入该文件。例如,给定 people.xml:
<people>
<managers>
<name>Jane Doe</name>
<reports>
<insert/>
</reports>
</managers>
<interns>
<insert/>
</interns>
</people>
和插入.xml:
<name>Abe Lincoln</name>
我们现在可以轻松地将 insert.xml 放在这两个位置:
$ xsltproc --stringparam file ./insert.xml --stringparam element insert ./insert.xslt ./people.xml
<?xml version="1.0"?>
<people>
<managers>
<name>Jane Doe</name>
<reports>
<insert><name>Abe Lincoln</name></insert>
</reports>
</managers>
<interns>
<insert><name>Abe Lincoln</name></insert>
</interns>
</people>
答案2
你可以envsubst
在这里使用:
bar=$(baz=$(cat baz.xml) envsubst '$baz' < bar.xml) envsubst '$bar' << 'EOF'
<foo>
$bar
</foo>
EOF
这将确保只有$bar
// ${bar}
/被扩展,而不是其他扩展(, , , ...)或其他变量$baz
,例如:${baz}
$(cmd)
`cmd`
$((arith))
${x#y}
bar=$(cat bar.xml)
baz=$(cat baz.xml)
eval "cat << EOF
<foo>
$bar
</foo>
EOF"
方法。
答案3
我找到了这个解决方案,不知道是否有更好的解决方案:
sed -i '/<bar>/r baz.xml' bar.xml
然后是定界符:
bar=$(cat bar.xml)
cat << EOF > out.xml
<foo>
$bar
</foo>
EOF
输出所需的结果:
<foo>
<bar>
<baz>baz</baz>
</bar>
</foo>