Добавьте/удалите теги xml с помощью bash script
У меня есть xml файл, который я хочу настроить с помощью bash script. Например, если у меня был этот xml:
<a>
<b>
<bb>
<yyy>
Bla
</yyy>
</bb>
</b>
<c>
<cc>
Something
</cc>
</c>
<d>
bla
</d>
</a>
(конфиденциальная информация удалена)
Я хотел бы написать bash script, который удалит раздел <b>
(или прокомментирует его), но сохранит остальную часть xml неповрежденной. Я довольно новый, весь сценарий. Мне было интересно, может ли кто-нибудь дать мне подсказку о том, на что я должен смотреть.
Я думал, что sed можно использовать, кроме sed - редактор строк. Я думаю, что было бы легко удалить теги <b>
, но я не уверен, что sed сможет удалить весь текст между тегами <b>
.
Мне также нужно написать script, чтобы добавить удаленный раздел.
Ответы
Ответ 1
Это не составит труда сделать в sed, так как sed также работает с диапазонами.
Попробуйте это (если xml находится в файле с именем foo.xml):
sed -i '/<b>/,/<\/b>/d' foo.xml
-i будет записывать изменение в исходный файл (используйте -i.bak, чтобы сохранить резервную копию оригинала)
Эта команда sed выполнит действие d (удалить) во всех строках, заданных диапазоном
# all of the lines between a line that matches <b>
# and the next line that matches <\/b>, inclusive
/<b>/,/<\/b>/
Итак, на простом английском языке эта команда удалит все строки между и включает строку с <b> и линия с </b>
Если вы предпочитаете комментировать строки, попробуйте один из них:
# block comment
sed -i 's/<b>/<!-- <b>/; s/<\/b>/<\/b> -->/' foo.xml
# comment out every line in the range
sed -i '/<b>/,/<\/b>/s/.*/<!-- & -->/' foo.xml
Ответ 2
Использование xmlstarlet:
#xmlstarlet ed -d "/a/b" file.xml > tmp.xml
xmlstarlet ed -d "//b" file.xml > tmp.xml
mv tmp.xml file.xml
Ответ 3
Вы можете использовать XSLT, например, это модифицированное преобразование идентичности. Он копирует все содержимое по умолчанию и имеет пустой шаблон для b
, который ничего не делает (фактически удаляет из вывода):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!--Identity transform copies all items by default -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--Empty template to match on b elements and prevent it from being copied to output -->
<xsl:template match="b"/>
</xsl:stylesheet>
Создайте bash script, который выполняет преобразование с помощью Java и утилиты командной строки Xalan следующим образом:
java org.apache.xalan.xslt.Process -IN foo.xml -XSL foo.xsl -OUT foo.out
В результате получится следующее:
<?xml version="1.0" encoding="UTF-16"?><a><c><cc>
Something
</cc></c><d>
bla
</d></a>
РЕДАКТИРОВАТЬ:, если вы предпочтете, чтобы b
закомментировал, чтобы упростить возврат, затем используйте эту таблицу стилей:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!--Identity transform copies all items by default -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--Match on b element, wrap in a comment and construct text representing XML structure by applying templates in "comment" mode -->
<xsl:template match="b">
<xsl:comment>
<xsl:apply-templates select="self::*" mode="comment" />
</xsl:comment>
</xsl:template>
<xsl:template match="*" mode="comment">
<xsl:value-of select="'<'"/>
<xsl:value-of select="name()"/>
<xsl:value-of select="'>'"/>
<xsl:apply-templates select="@*|node()" mode="comment" />
<xsl:value-of select="'</'"/>
<xsl:value-of select="name()"/>
<xsl:value-of select="'>'"/>
</xsl:template>
<xsl:template match="text()" mode="comment">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="@*" mode="comment">
<xsl:value-of select="name()"/>
<xsl:text>="</xsl:text>
<xsl:value-of select="."/>
<xsl:text>" </xsl:text>
</xsl:template>
</xsl:stylesheet>
Он производит этот вывод:
<?xml version="1.0" encoding="UTF-16"?><a><!--<b><bb><yyy>
Bla
</yyy></bb></b>--><c><cc>
Something
</cc></c><d>
bla
</d></a>
Ответ 4
Если вы хотите наиболее подходящую замену для sed
для XML-данных, это будет XSLT-процессор. Подобно sed
это сложный язык, но специализированный для задачи преобразований XML-to-anything.
С другой стороны, это, кажется, точка, в которой я бы серьезно подумал о переходе на настоящий язык программирования, например Python.
Ответ 5
@OP, вы можете использовать awk, например
$ cat file
<a>
some text before <b>
<bb>
<yyy>
Bla
</yyy>
</bb>
</b> some text after
<c>
<cc>
Something
</cc>
</c>
<d>
bla
</d>
</a>
$ awk 'BEGIN{RS="</b>"}/<b>/{gsub(/<b>.*/,"")}1' file
<a>
some text before
some text after
<c>
<cc>
Something
</cc>
</c>
<d>
bla
</d>
</a>
Ответ 6
# edit file inplace
xmlstarlet ed -L -d "//b" file.xml