Регулярное выражение для отступа XML-файла

Можно ли написать REGEX (замена поиска), который при запуске в строке XML будет выводить эту строку XML с красивым отступом?

Если да, то что такое REGEX :)


person Toby Allen    schedule 12.02.2009    source источник


Ответы (7)


Можно ли написать REGEX (замена поиска), который при запуске в строке XML [... что-нибудь]

No.

Используйте синтаксический анализатор XML, чтобы прочитать строку, а затем сериализатор XML, чтобы записать ее обратно в «красивом» режиме.

Каждый XML-процессор имеет свои собственные параметры, поэтому они зависят от платформы, но вот несколько многословный способ, который работает в реализациях, совместимых с DOM уровня 3 LS:

input= implementation.createLSInput();
input.stringData= unprettyxml;
parser= implementation.createLSParser(implementation.MODE_SYNCHRONOUS, null);
document= parser.parse(input);
serializer= implementation.createLSSerializer();
serializer.domConfig.setParameter("format-pretty-print", true);
prettyxml= serializer.writeToString(document);
person bobince    schedule 12.02.2009
comment
Если бы можно было кричать онлайн, я бы много кричал первые два предложения этого поста. - person Robert Rossney; 13.02.2009

Сделать это было бы намного проще, если бы вы не использовали регулярное выражение. На самом деле я даже не уверен, что это возможно с регулярным выражением.

Большинство языков имеют XML-библиотеки, которые очень упростили бы эту задачу. Какой язык вы используете?

person Greg    schedule 12.02.2009

Я не знаю, может ли регулярное выражение в отдельности сделать красивый формат произвольного ввода XML. Вам понадобится регулярное выражение, применяемое программой, чтобы найти тег, найти соответствующие закрывающие теги (если тег не закрывается самостоятельно) и так далее. Использование регулярных выражений для решения этой проблемы на самом деле означает использование неправильного инструмента для работы. Самый простой способ красиво распечатать XML — это использовать анализатор XML, прочитать его, установить соответствующие параметры сериализации, а затем снова сериализовать XML.

Почему вы хотите использовать регулярное выражение для решения этой проблемы?

person Eddie    schedule 12.02.2009

Использование регулярного выражения для этого будет кошмаром. Отследить уровень отступа на основе иерархии узлов будет практически невозможно. Возможно, механизм регулярных выражений Perl 5.10 может помочь, поскольку теперь он реентерабельный. Но не будем идти по этому пути... Кроме того, вам нужно будет принять во внимание разделы CDATA, которые могут встраивать XML-декларации, которые необходимо игнорировать отступом и сохранять в неизменном виде.

Держитесь ДОМ. Как было предложено в другом ответе, некоторые библиотеки уже предоставляют функцию, которая сделает для вас отступ дерева DOM. Если его не построить, это будет намного проще, чем создание и поддержка регулярных выражений, которые будут выполнять ту же задачу.

person potyl    schedule 12.02.2009

Описанное здесь регулярное выражение темного вуду отлично работает.
http://www.perlmonks.org/?node_id=261292
Его основное преимущество по сравнению с XML::LibXMl и другими заключается в том, что он на порядок быстрее.

person Zorglub    schedule 30.07.2010

Это было бы достижимо только с несколькими регулярными выражениями, которые будут работать как конечный автомат.

То, что вы ищете, гораздо лучше подходит для синтаксического анализатора манжеты.

person DevelopingChris    schedule 12.02.2009
comment
Одно регулярное выражение уже является конечным автоматом. Я почти уверен, что это было бы возможно с регулярным выражением (при условии, что поддерживается просмотр вперед), но результат был бы чертовски уродливым. - person Drew Noakes; 12.02.2009
comment
Это на самом деле теоретически невозможно. XML является контекстно-свободным языком, и в нем нельзя создавать отступы с помощью регулярных выражений (обычный язык). См. Тип 3 и Тип 2 в иерархии языков Хомского: en.wikipedia.org/wiki/Chomsky_hierarchy - person Hristo Vrigazov; 21.06.2019

Из этой ссылки :

  private static Regex indentingRegex=new Regex(@"\<\s*(?<tag>[\w\-]+)(\s+[\w\-]+\s*=\s*""[^""]*""|'[^']*')*\s*\>[^\<]*\<\s*/\s*\k<tag>\s*\>|\<[!\?]((?<=!)--((?!--\>).)*--\>|(""[^""]*""|'[^']'|[^>])*\>)|\<\s*(?<closing>/)?\s*[\w\-]+(\s+[\w\-]+\s*=\s*""[^""]*""|'[^']*')*\s*((/\s*)|(?<opening>))\>|[^\<]*", RegexOptions.ExplicitCapture|RegexOptions.Singleline);

  public static string IndentXml(string xml) {
        StringBuilder result=new StringBuilder(xml.Length*2);
        int indent=0;
        for (Match match=indentingRegex.Match(xml); match.Success; match=match.NextMatch()) {
              if (match.Groups["closing"].Success)
                    indent--;
              result.AppendFormat("{0}{1}\r\n", new String(' ', indent*2), match.Value);
              if (match.Groups["opening"].Success&&(!match.Groups["closing"].Success))
                    indent++;
        }
        return result.ToString();
  }
person 0ez    schedule 10.12.2015