将XML标记值移动到其他标记
我正在尝试使用可以在bash中运行的命令创建一个简单的脚本,该命令允许我获取XML文件的值并重新排列它们。以此示例文件为例:将XML标记值移动到其他标记,xml,bash,Xml,Bash,我正在尝试使用可以在bash中运行的命令创建一个简单的脚本,该命令允许我获取XML文件的值并重新排列它们。以此示例文件为例: <item1> <line>ASDF</line> <importantLine1>AAA</importantLine1> <importantLine2>BBB</importantLine2> <junkLine>CCC</junkL
<item1>
<line>ASDF</line>
<importantLine1>AAA</importantLine1>
<importantLine2>BBB</importantLine2>
<junkLine>CCC</junkLine>
<importantLine3>DDD</importantLine3>
<nest>
<nestedLine>EEE</nestedLine>
</nest>
</item1>
<item2>
<line>ASDF</line>
<importantLine1>AAA</importantLine1>
<importantLine2>BBB</importantLine2>
<junkLine>CCC</junkLine>
<importantLine3>DDD</importantLine3>
<nest>
<nestedLine>EEE</nestedLine>
</nest>
</item2>
<item3>
<line>ASDF</line>
<importantLine1>AAA</importantLine1>
<importantLine2>BBB</importantLine2>
<junkLine>CCC</junkLine>
<importantLine3>DDD</importantLine3>
<nest>
<nestedLine>EEE</nestedLine>
</nest>
</item3>
ASDF
AAA
BBB
CCC
DDD
EEE
ASDF
AAA
BBB
CCC
DDD
EEE
ASDF
AAA
BBB
CCC
DDD
EEE
我想让输出看起来像这样,将一些标记中的值移动到一个标记中:
<item1>
<line>ASDF</line>
<importantLine2>DDD "AAA" BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item1>
<item2>
<line>ASDF</line>
<importantLine2>DDD "AAA" BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item2>
<item3>
<line>ASDF</line>
<importantLine2>DDD "AAA" BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item3>
ASDF
DDD“AAA”BBB[EEE]
CCC
ASDF
DDD“AAA”BBB[EEE]
CCC
ASDF
DDD“AAA”BBB[EEE]
CCC
如果有什么不同的话,我想学习如何移动这些值,而不仅仅是一个让它发生的答案。“教人钓鱼…”使用XSLT文件可以实现这一点。元素的顺序并不完全正确,但如果没有任何标准,这是最好的。如有必要,可使用
等命令对输出进行排序
您必须将所有项???
元素放在一个根元素中,此解决方案才能工作
reorder.xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="*[starts-with(local-name(),'item')]">
<xsl:copy>
<xsl:copy-of select="line" />
<importantLine2>
<xsl:for-each select="*[starts-with(local-name(),'importantLine')]">
<xsl:value-of select="concat(text(),' ')"/>
</xsl:for-each>
<xsl:for-each select="nest/nestedLine">
<xsl:text>[</xsl:text><xsl:value-of select="concat(text(),' ')"/><xsl:text>]</xsl:text>
</xsl:for-each>
</importantLine2>
<xsl:copy-of select="junkLine" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出为:
<item1>
<line>ASDF</line>
<importantLine2>AAA BBB DDD [EEE ]</importantLine2>
<junkLine>CCC</junkLine>
</item1>
<item2>
<line>ASDF</line>
<importantLine2>AAA BBB DDD [EEE ]</importantLine2>
<junkLine>CCC</junkLine>
</item2>
<item3>
<line>ASDF</line>
<importantLine2>AAA BBB DDD [EEE ]</importantLine2>
<junkLine>CCC</junkLine>
</item3>
ASDF
AAA BBB DDD[EEE]
CCC
ASDF
AAA BBB DDD[EEE]
CCC
ASDF
AAA BBB DDD[EEE]
CCC
xmlstarlet
解决方案:
假设具有“根”(主)节点的有效XML文档:
-编辑模式ed
-省略XML声明-O
()
-更新操作;完整签名:-u
-u或--update-v(--value)-x(--expr)
-删除操作;完整签名:-d
-d或--delete
输出:
<root>
<item1>
<line>ASDF</line>
<importantLine2>DDD AAA BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item1>
<item2>
<line>ASDF</line>
<importantLine2>DDD AAA BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item2>
<item3>
<line>ASDF</line>
<importantLine2>DDD AAA BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item3>
</root>
ASDF
DDD AAA BBB[EEE]
CCC
ASDF
DDD AAA BBB[EEE]
CCC
ASDF
DDD AAA BBB[EEE]
CCC
为什么要使用bash?使用xsltproc
(仅25k)和XSLT模板肯定会更容易。应该已经澄清了。我指的是可以在bash中运行的命令。很抱歉我将快速编辑它,我建议使用xmlint和xpath。其他常见的XML工具有xmlstarlet
和xmlto
。如果Bash只是指shell的内置工具,或者只指通常安装的核心工具,如Awk和sed
,那么您将受到伤害。
xmlstarlet ed -O -u "//importantLine2" \
-x 'concat(parent::*/importantLine3, " ", parent::*/importantLine1, " ", . ,
" [", parent::*//nestedLine, "]")' \
-d '//importantLine1 | //importantLine3 | //nest' xmlfile
<root>
<item1>
<line>ASDF</line>
<importantLine2>DDD AAA BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item1>
<item2>
<line>ASDF</line>
<importantLine2>DDD AAA BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item2>
<item3>
<line>ASDF</line>
<importantLine2>DDD AAA BBB [EEE]</importantLine2>
<junkLine>CCC</junkLine>
</item3>
</root>