Xmlstarlet / Sh - 将节点的内容复制到新节点/连接现有节点
Xmlstarlet / Sh - Copy content of a node into a new node / concat existing
我有以下 xml(例如)
<?xml version="1.0"?>
<gameList>
<game>
<path>./sunsetbl.zip</path>
<name>sunsetbl</name>
<playcount>8</playcount>
<lastplayed>20180924T214132</lastplayed>
</game>
<game>
<path>./ssriders.zip</path>
<name>Sunset Riders (4 Players ver EAC)</name>
<playcount>4</playcount>
<lastplayed>20181030T013801</lastplayed>
</game>
<game>
<path>./kof97.zip</path>
<name>The King of Fighters '97 (NGM-2320)</name>
<playcount>2</playcount>
<lastplayed>20181030T035949</lastplayed>
</game>
<game>
<path>./dino.zip</path>
<name>Cadillacs and Dinosaurs (World 930201)</name>
<favorite>true</favorite>
<playcount>26</playcount>
<lastplayed>20181030T043441</lastplayed>
</game>
<game>
<path>./kof98n.zip</path>
<name>kof98n</name>
<playcount>1</playcount>
<lastplayed>20181031T001024</lastplayed>
</game>
</gameList>
好吧,我正在尝试编写一个 sh 脚本并在其上使用 xmlstarlet。对于每个游戏节点,我想复制路径节点并将其插入到一个名为描述的新节点中,如果描述已经存在,则将其连接到那里的现有文本。
我真的很菜鸟,这是我到现在为止能做的。
#!/bin/bash
set -e
shopt -s nullglob
for file in *.xml
do
FILENAME=`xmlstarlet sel -t -m "/gameList/game" -v path $file`;
echo "Appending $FILENAME into description on $file";
xmlstarlet ed -L -s "/gameList/game" -t elem -n description -v "$FILENAME" $file;
done
当然,结果很糟糕,所有路径值都在一行中并复制到每个游戏节点,这就是它显示的结果
<?xml version="1.0"?>
<gameList>
<game>
<path>./sunsetbl.zip</path>
<name>sunsetbl</name>
<playcount>8</playcount>
<lastplayed>20180924T214132</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
<game>
<path>./ssriders.zip</path>
<name>Sunset Riders (4 Players ver EAC)</name>
<playcount>4</playcount>
<lastplayed>20181030T013801</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
<game>
<path>./kof97.zip</path>
<name>The King of Fighters '97 (NGM-2320)</name>
<playcount>2</playcount>
<lastplayed>20181030T035949</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
<game>
<path>./dino.zip</path>
<name>Cadillacs and Dinosaurs (World 930201)</name>
<favorite>true</favorite>
<playcount>26</playcount>
<lastplayed>20181030T043441</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
<game>
<path>./kof98n.zip</path>
<name>kof98n</name>
<playcount>1</playcount>
<lastplayed>20181031T001024</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
</gameList>
我很乐意对此提供任何帮助。
如果可以使用单独的 XSLT 文件,解决方案如下。
使用此 XSLT 文件(此处命名为 trans.xslt
):
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- Add 'path' value to existing 'description' element -->
<xsl:template match="description">
<xsl:copy>
<xsl:value-of select="concat(.,../path)" />
</xsl:copy>
</xsl:template>
<!-- Create new 'description' element -->
<xsl:template match="game[not(description)]">
<xsl:copy>
<xsl:copy-of select="node()|@*" />
<description>
<xsl:value-of select="path" />
</description>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
并用这个脚本调用它:
#!/bin/bash
set -e
shopt -s nullglob
for file in *.xml
do
xmlstarlet tr trans.xslt "$file" > "$file.new.xml"
done
这将创建扩展名为 filename.new.xml
的新文件。
我有以下 xml(例如)
<?xml version="1.0"?>
<gameList>
<game>
<path>./sunsetbl.zip</path>
<name>sunsetbl</name>
<playcount>8</playcount>
<lastplayed>20180924T214132</lastplayed>
</game>
<game>
<path>./ssriders.zip</path>
<name>Sunset Riders (4 Players ver EAC)</name>
<playcount>4</playcount>
<lastplayed>20181030T013801</lastplayed>
</game>
<game>
<path>./kof97.zip</path>
<name>The King of Fighters '97 (NGM-2320)</name>
<playcount>2</playcount>
<lastplayed>20181030T035949</lastplayed>
</game>
<game>
<path>./dino.zip</path>
<name>Cadillacs and Dinosaurs (World 930201)</name>
<favorite>true</favorite>
<playcount>26</playcount>
<lastplayed>20181030T043441</lastplayed>
</game>
<game>
<path>./kof98n.zip</path>
<name>kof98n</name>
<playcount>1</playcount>
<lastplayed>20181031T001024</lastplayed>
</game>
</gameList>
好吧,我正在尝试编写一个 sh 脚本并在其上使用 xmlstarlet。对于每个游戏节点,我想复制路径节点并将其插入到一个名为描述的新节点中,如果描述已经存在,则将其连接到那里的现有文本。
我真的很菜鸟,这是我到现在为止能做的。
#!/bin/bash
set -e
shopt -s nullglob
for file in *.xml
do
FILENAME=`xmlstarlet sel -t -m "/gameList/game" -v path $file`;
echo "Appending $FILENAME into description on $file";
xmlstarlet ed -L -s "/gameList/game" -t elem -n description -v "$FILENAME" $file;
done
当然,结果很糟糕,所有路径值都在一行中并复制到每个游戏节点,这就是它显示的结果
<?xml version="1.0"?>
<gameList>
<game>
<path>./sunsetbl.zip</path>
<name>sunsetbl</name>
<playcount>8</playcount>
<lastplayed>20180924T214132</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
<game>
<path>./ssriders.zip</path>
<name>Sunset Riders (4 Players ver EAC)</name>
<playcount>4</playcount>
<lastplayed>20181030T013801</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
<game>
<path>./kof97.zip</path>
<name>The King of Fighters '97 (NGM-2320)</name>
<playcount>2</playcount>
<lastplayed>20181030T035949</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
<game>
<path>./dino.zip</path>
<name>Cadillacs and Dinosaurs (World 930201)</name>
<favorite>true</favorite>
<playcount>26</playcount>
<lastplayed>20181030T043441</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
<game>
<path>./kof98n.zip</path>
<name>kof98n</name>
<playcount>1</playcount>
<lastplayed>20181031T001024</lastplayed>
<description>./sunsetbl.zip./ssriders.zip./kof97.zip./dino.zip./kof98n.zip</description>
</game>
</gameList>
我很乐意对此提供任何帮助。
如果可以使用单独的 XSLT 文件,解决方案如下。
使用此 XSLT 文件(此处命名为 trans.xslt
):
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- Add 'path' value to existing 'description' element -->
<xsl:template match="description">
<xsl:copy>
<xsl:value-of select="concat(.,../path)" />
</xsl:copy>
</xsl:template>
<!-- Create new 'description' element -->
<xsl:template match="game[not(description)]">
<xsl:copy>
<xsl:copy-of select="node()|@*" />
<description>
<xsl:value-of select="path" />
</description>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
并用这个脚本调用它:
#!/bin/bash
set -e
shopt -s nullglob
for file in *.xml
do
xmlstarlet tr trans.xslt "$file" > "$file.new.xml"
done
这将创建扩展名为 filename.new.xml
的新文件。