Xmlstarlet / Sh - копировать содержимое узла в новый узел / существующий конкат - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть следующий 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 на нем.Для каждого игрового узла я хочу скопировать узел пути и вставить его в новый узел с именем description, и, если описание уже существует, объединить его с существующим текстом.

Я действительно нуб на этом и на этомэто то, что я смог сделать до сих пор.

#!/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>

Я с удовольствием оценил былюбая помощь в этом.

1 Ответ

0 голосов
/ 04 декабря 2018

Если вы можете использовать отдельный файл 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.

...