如何在树中移动 xml 文件中的元素
How to move elements in an xml file within the tree
我有一个 xml 文件,格式如下:
<results>
<sequence-name>name1</sequence-name>
<repetitions>
<window>
<key1>1</key1>
</window>
</repetitions>
<sequence-name>name2</sequence-name>
<repetitions>
<window>
<key1>4</key1>
</window>
</repetitions>
</results>
我想移动元素 sequence-name
使其成为 window
中的第一个元素,因此输出应如下所示:
<results>
<repetitions>
<window>
<sequence-name>name1</sequence-name>
<key1>1</key1>
</window>
</repetitions>
<repetitions>
<window>
<sequence-name>name2</sequence-name>
<key1>4</key1>
</window>
</repetitions>
</results>
我尝试使用 grep 生成两个文件,一个只包含带有 <sequence-name>
的行,另一个包含所有其他行。但我不知道如何将包含 <sequence-name>
的行插入到我想要的位置。我猜有一个使用 sed/aw
k 的解决方案。我也很乐意使用 xmlstarlet
.
这样的工具
如果您的文件始终格式正确并且在 xmlstarlet 中非常重要:
$ awk '/<sequence-name>/{s=[=10=];next} {print} /<window>/{print s}' file
<results>
<repetitions>
<window>
<sequence-name>name1</sequence-name>
<key1>1</key1>
</window>
</repetitions>
<repetitions>
<window>
<sequence-name>name2</sequence-name>
<key1>4</key1>
</window>
</repetitions>
</results>
如果您关心缩进:
$ awk '/<sequence-name>/{s=[=11=]; next} {print} /<window>/{indent=[=11=]; sub(/[^[:space:]].*/," ",indent); sub(/^[[:space:]]*/,indent,s); print s}' file
<results>
<repetitions>
<window>
<sequence-name>name1</sequence-name>
<key1>1</key1>
</window>
</repetitions>
<repetitions>
<window>
<sequence-name>name2</sequence-name>
<key1>4</key1>
</window>
</repetitions>
</results>
下面的样式表应该可以解决问题:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/ | node()">
<xsl:copy>
<xsl:apply-templates select="node()[not(self::sequence-name)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="window">
<xsl:copy>
<xsl:copy-of select="preceding::sequence-name[1]" />
<xsl:apply-templates select="key1"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
您可以使用 xsltproc stylesheet data
或 xmlstarlet tr stylesheet data
应用它。
另一种方法,只使用 sed:
$ sed '/<sequence-name>/{s/^/ /; h; d;}; /<window>/G;' file
<results>
<repetitions>
<window>
<sequence-name>name1</sequence-name>
<key1>1</key1>
</window>
</repetitions>
<repetitions>
<window>
<sequence-name>name2</sequence-name>
<key1>4</key1>
</window>
</repetitions>
</results>
我有一个 xml 文件,格式如下:
<results>
<sequence-name>name1</sequence-name>
<repetitions>
<window>
<key1>1</key1>
</window>
</repetitions>
<sequence-name>name2</sequence-name>
<repetitions>
<window>
<key1>4</key1>
</window>
</repetitions>
</results>
我想移动元素 sequence-name
使其成为 window
中的第一个元素,因此输出应如下所示:
<results>
<repetitions>
<window>
<sequence-name>name1</sequence-name>
<key1>1</key1>
</window>
</repetitions>
<repetitions>
<window>
<sequence-name>name2</sequence-name>
<key1>4</key1>
</window>
</repetitions>
</results>
我尝试使用 grep 生成两个文件,一个只包含带有 <sequence-name>
的行,另一个包含所有其他行。但我不知道如何将包含 <sequence-name>
的行插入到我想要的位置。我猜有一个使用 sed/aw
k 的解决方案。我也很乐意使用 xmlstarlet
.
如果您的文件始终格式正确并且在 xmlstarlet 中非常重要:
$ awk '/<sequence-name>/{s=[=10=];next} {print} /<window>/{print s}' file
<results>
<repetitions>
<window>
<sequence-name>name1</sequence-name>
<key1>1</key1>
</window>
</repetitions>
<repetitions>
<window>
<sequence-name>name2</sequence-name>
<key1>4</key1>
</window>
</repetitions>
</results>
如果您关心缩进:
$ awk '/<sequence-name>/{s=[=11=]; next} {print} /<window>/{indent=[=11=]; sub(/[^[:space:]].*/," ",indent); sub(/^[[:space:]]*/,indent,s); print s}' file
<results>
<repetitions>
<window>
<sequence-name>name1</sequence-name>
<key1>1</key1>
</window>
</repetitions>
<repetitions>
<window>
<sequence-name>name2</sequence-name>
<key1>4</key1>
</window>
</repetitions>
</results>
下面的样式表应该可以解决问题:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/ | node()">
<xsl:copy>
<xsl:apply-templates select="node()[not(self::sequence-name)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="window">
<xsl:copy>
<xsl:copy-of select="preceding::sequence-name[1]" />
<xsl:apply-templates select="key1"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
您可以使用 xsltproc stylesheet data
或 xmlstarlet tr stylesheet data
应用它。
另一种方法,只使用 sed:
$ sed '/<sequence-name>/{s/^/ /; h; d;}; /<window>/G;' file
<results>
<repetitions>
<window>
<sequence-name>name1</sequence-name>
<key1>1</key1>
</window>
</repetitions>
<repetitions>
<window>
<sequence-name>name2</sequence-name>
<key1>4</key1>
</window>
</repetitions>
</results>