Изменить текст тега в bash - PullRequest
       4

Изменить текст тега в bash

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

У меня есть много текстовых файлов в формате XML, например:

<TITLE>title</TITLE>
<TEXT>text</TEXT>

Но мне нужно изменить текст тегов на что-то вроде этого:

<field name="title">title</field>
<field name="text">text</field>

Iя пытаюсь написать небольшой скрипт на bash и использовать команду sed для изменения текста тегов.

sed "s/<TEXT>/<field name"text">/g"

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

Спасибодля любой помощи.

РЕДАКТИРОВАТЬ: Добавлен пример ввода и вывода.

Вход

<?xml version="1.0" encoding="UTF-8"?>
<DOC>
    <DOCID>MF-20020103001</DOCID>
    <DATE>01/03/02</DATE>
    <TITLE>Example title</TITLE>
    <TEXT>Very long text...</TEXT>
</DOC>

Выход

<?xml version="1.0" encoding="UTF-8"?>
<doc>
    <field name="docid">MF-20020103001</field>
    <field name="date">01/03/02</field>
    <field name="title">Example title</field>
    <field name="text">Very long text...</field>
</doc>

Ответы [ 4 ]

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

Вы можете использовать любой процессор XSLT-1.0, например xsltproc, для преобразования вашего входного XML в желаемый выходной XML.

Это возможный файл XSLT-1.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/DOC">
      <doc>
        <xsl:apply-templates select="node()|@*" />
      </doc>
    </xsl:template>

    <xsl:template match="*">
      <field name="{translate(local-name(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')}">
        <xsl:value-of select="text()" />
      </field>
    </xsl:template>

</xsl:stylesheet>

Какой вывод:

<?xml version="1.0" encoding="UTF-8"?>
<doc>
    <field name="docid">MF-20020103001</field>
    <field name="date">01/03/02</field>
    <field name="title">Example title</field>
    <field name="text">Very long text...</field>
</doc>

Вы можете получить это, используя процессор XSLT xsltproc:

xsltproc input.xslt input.xml
0 голосов
/ 08 декабря 2018

Вот ужасный ответ, который очень утомителен, но нуждается в уточнении:

sed -e "s/<\([^/>]*\)>/<field name='\1'>/g" -e "s/<\/\([^.]*\)>/<\/field>/" 

Вот вывод с учетом вашего ввода:

<field name='?xml version="1.0" encoding="UTF-8"?'>
<field name='DOC'>
    <field name='DOCID'>MF-20020103001</field>
    <field name='DATE'>01/03/02</field>
    <field name='TITLE'>Example title</field>
    <field name='TEXT'>Very long text...</field>
</field>

Вы можете увидеть очевидные проблемы с моим ответом:

  1. ? Xml директива была достигнута
  2. элемент был изменен
  3. Мы не прописывали атрибут
  4. Мы бы, вероятно,испортите любые другие элементы с атрибутами (как? xml выше)

Первый совет, который вы получили, был лучшим.Используйте синтаксический анализатор XML.Если вы хотите, вы можете сходить с ума с XSLT.Затем вы можете сгенерировать таблицу стилей XML (.xsl) для определения преобразования.

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

Вот разумный ответ, поскольку он использует инструмент, предназначенный для XML.

#!/bin/bash

function transform() {

  {
  cat  <<-'EOF'
    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

    <xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'" />
    <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />



    <xsl:output method="xml" encoding="UTF-8"/>

    <xsl:template match="/DOC">
    <doc> 
      <xsl:apply-templates  />
    </doc>
    </xsl:template>

    <xsl:template match="*">
    <field> 
    <xsl:attribute name="name"><xsl:value-of select="translate(local-name(),$uppercase,$lowercase)"/></xsl:attribute>
    <xsl:apply-templates />
    </field>
    </xsl:template>



    </xsl:stylesheet>
EOF
  } |  xsltproc - $1 

}


transform $1

Вот вывод, который я получаю, когда запускаю ваш ввод:

<?xml version="1.0" encoding="UTF-8"?>
<doc>
    <field name="docid">MF-20020103001</field>
    <field name="date">01/03/02</field>
    <field name="title">Example title</field>
    <field name="text">Very long text...</field>
</doc>

РЕДАКТИРОВАТЬ: я изменилЗапрограммируйте выше, чтобы преобразовать имена элементов верхнего регистра в нижний регистр.Кредит переходит к Джону W с Как я могу преобразовать строку в верхний или нижний регистр с помощью XSLT?

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

С обычным советом, что лучше проанализировать xml с парсером xml, если вы можете рассчитывать на структуру, как показано в примере:

$ awk 'BEGIN { FS = "<|>"; OFS = ""} NF > 3 { $0 = "    <field name=\"" tolower($2) "\">"$3"</field>" }1' file
<?xml version="1.0" encoding="UTF-8"?>
<DOC>
    <field name="docid">MF-20020103001</field>
    <field name="date">01/03/02</field>
    <field name="title">Example title</field>
    <field name="text">Very long text...</field>
</DOC>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...