Как получить плоский XML, чтобы внешние объекты объединялись на верхнем уровне

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

У меня есть куча файлов XML, которые кто-то в своей бесконечной мудрости решил разбить на несколько файлов, используя теги, что в результате делает их отладку/редактирование огромным P-i-t-A. Поэтому я ищу:

  1. Способ в VIM открывать их в одном буфере (желательно, чтобы изменения сохранялись в правильных внешних файлах сущностей), ИЛИ;
  2. Способ расширения файлов в VIM, чтобы внешние сущности считывались и заменялись в буфере, ИЛИ;
  3. простой способ bash/sed/python сделать это в командной строке (или в .vimrc)

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

Вот пример макета того, как выглядит файл верхнего уровня:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foobar PUBLIC "foobar:dtd" "foobar.dtd" [

        <!ENTITY foo SYSTEM "foo.xml">

        <!ENTITY bar SYSTEM "bar.xml">
]>
<foo>
        <params>
                &foo;
        </params>
        <bar>
                &bar;
        </bar>
</foo>

РЕДАКТИРОВАТЬ: список расположен в порядке предпочтения - если нет доступных решений 1. или 2., награда достается лучшему #3...

EDIT 2: похоже, что ответ @Gaby работает, но, к сожалению, только частично, если я не делаю что-то не так - я напишу какой-нибудь инструмент, используя его ответ, и опубликую его здесь для улучшений. Конечно, решение №1 или №2 будет оценено... :)

РЕДАКТИРОВАТЬ 3: Хорошо, лучший не-Emacs-ответ получит награду;)

Заключение. Благодаря @hcayless у меня теперь есть работающее решение №2. Я добавил:

autocmd BufReadPost,FileReadPost *.xml silent %!xmllint --noent - 2> /dev/null

к моему .vimrc и все в порядке.


person Kimvais    schedule 07.01.2010    source источник
comment
Можно ли это сделать с помощью xslt?   -  person michael    schedule 08.01.2010
comment
Я не видел этого раньше, но, видимо, это честная часть XML. xml.com/pub/a/98/08/xmlqna2.html — одно из объяснений, которое я нашел для этого.   -  person Mike Seplowitz    schedule 09.01.2010
comment
Да, это действительно и, следовательно, в два раза раздражает :)   -  person Kimvais    schedule 09.01.2010
comment
Я мог бы помочь вам с 3, но обязательно ли это должно быть обратимым? Или поможет одноразовое решение (расширяйте сейчас, никогда не возвращайтесь к старой системе).   -  person reto    schedule 09.01.2010
comment
Любая помощь приветствуется, обратимость будет бонусом, но если нет решений №1 или №2, придется делать необратимое №3...   -  person Kimvais    schedule 09.01.2010


Ответы (3)


Если у вас установлена ​​libxml2, то xmllint, вероятно, сделает это за вас. В зависимости от вашей настройки вам может понадобиться больше параметров, но для вашего примера

xmllint --noent foobar.xml

напечатает ваш файл на стандартный вывод со всеми разрешенными объектами. Должно быть достаточно просто обернуть вокруг него несколько сценариев bash, чтобы делать то, что вам нужно.

person hcayless    schedule 13.01.2010
comment
Работает отлично. Спасибо! - теперь мне просто нужно добавить, чтобы это делалось автоматически в .vimrc при открытии .xml файлов. - person Kimvais; 13.01.2010

Для варианта №3 вы можете взглянуть на pixdom и посмотреть на документация по адресу pxdom 1.5 Реализация DOM на Python

Параметры конфигурации DOM

Результат операции синтаксического анализа зависит от параметров, установленных в отображении LSParser.domConfig. По умолчанию, в соответствии со спецификацией DOM, все разделы CDATA будут заменены простыми текстовыми узлами, а все связанные ссылки на сущности будут заменены содержимым упомянутой сущности. Сюда входят ссылки на внешние сущности и внешнее подмножество.

он включает сериализатор для сохранения документа в файл.

person Gabriele Petrioli    schedule 10.01.2010

Вы ищете что-то подобное?

#!/opt/local/bin/python
import sys
if len(sys.argv) < 2:
    print "some files needed."
    sys.exit()

final = """
<?xml version="1.0" encoding="ISO-8859-1"?>
<nodes>
"""
for a in sys.argv[1:]:
    ca = a.replace(".xml","")
    final += "<" + ca + ">\n"
    infile = open(a)
    final += infile.read()
    final += "</" + ca + ">\n"  

final += "</nodes>\n"

outfile = open("final.xml", "w")
outfile.write(final)
outfile.close()
person Vlad the Impala    schedule 13.01.2010