Я хочу добавить префикс пространства имен к тегам пространства имен по умолчанию XML-документа из оболочки

Я хочу добавить префикс пространства имен к тегам пространства имен по умолчанию XML-документа из оболочки

У меня есть файл SVG, который представляет собой XML-документ:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
  <defs
     id="defs2">
  <!-- a lot of stuff> </defs>
  <!-- more stuff-->
</svg>

Я хочу добавить префикс svg: ко всем тегам, соответствующим пространству имен по умолчанию, чтобы получить следующий вывод:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg:svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
  <svg:defs
     id="defs2">
  <!-- a lot of stuff> </svg:defs>
  <!-- more stuff-->
</svg:svg>

Я уверен, что это возможно сделать одной или несколькими командными строками из оболочки, используяxmllintи/илиxmlstarletно я не могу этого сделать.

решение1

Прошло много времени с тех пор, как вы спрашивали. Тем не менее...

xmlstarlet edit's -r/ --renameдействие требует буквального значения для нового имени, поэтому функции XPath отсутствуют. Однако, xmlstarlet select может использоваться как генератор кода для создания команды редактирования:

xmlstarlet select -t \
  --var sq -o "'" -b \
  -o 'xmlstarlet edit --pf \' -n \
  -m 'set:distinct(//_:*)' \
    -o '  -r ' -v 'concat($sq,"//_:",local-name(),$sq)' \
    -o '  -v ' -v 'concat($sq,"svg:",local-name(),$sq)' -o ' \' -n \
  -b \
  -f -n \
file.xml 

где

  • выражение //_:*соответствует всем узлам элементов в пространстве имен по умолчанию ( _сокращение находится вxmlstarlet руководство пользователя)
  • функция EXSLTset:distinct устраняет дубликаты
  • -oвыводит строковый литерал, -nновую строку, -fвходной путь/URL (но -для stdin)
  • -bзавершает текущий контейнер ( -m, --varбез =, ао)
  • добавление -Cопции перед -tсписком сгенерированного кода XSLT

Выход:

xmlstarlet edit --pf \
  -r '//_:svg'  -v 'svg:svg' \
  -r '//_:defs'  -v 'svg:defs' \
file.xml

где

  • -P/ --pfсохраняет исходное форматирование
  • добавление параметра -L/ --inplaceпосле editподдерживает редактирование на месте (не в руководстве пользователя, а в xmlstarlet.txt)

Чтобы выполнить вывод как скрипт оболочки:

xmlstarlet-select-command | sh -s > result.xml

Если вы хотите избежать EXSLT, вместо этого -m '//_:*' --sort 'A:T:-' . передайте вывод через uniq, или просто -m '//_:*'с возможными дубликатами.

решение2

Использование xmlstarletв особенно жестокой манере (жду правильный xpath)

for x in $(xmlstarlet sel -t -m "//*" -n -v "name()" file1.xml | sort | uniq); do 
    xmlstarlet ed -r "//svg:$x" -v "svg:$x" file1.xml > tmp.xml;
    mv tmp.xml file1.xml;
done

Поскольку вы уже объявили пространство имен svg, вам необходимо вызвать его, чтобы xpathизменить буквальное значение имен узлов.

Связанный контент