使用正则表达式缩进XML文件

4

是否有可能编写一个正则表达式(搜索替换),当在XML字符串上运行时,会将该XML字符串漂亮地缩进输出?

如果可以的话,正则表达式是什么呢 :)

7个回答

5

如果您不使用正则表达式,这样做会简单得多。实际上,我甚至不确定是否可以使用正则表达式。

大多数语言都有XML库,使此任务非常简单。您使用的是哪种语言?


5

有没有可能编写一个正则表达式(搜索替换),当在XML字符串上运行时[...anything]

不行。

使用XML解析器读取字符串,然后使用XML序列化程序以“漂亮”的模式重新写入它。

每个XML处理器都有自己的选项,因此这取决于平台,但以下是在DOM Level 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);

如果在网上真的能够大喊大叫,我会经常大声喊出这篇文章的前两句话。 - Robert Rossney

3
我不知道单独使用正则表达式是否能够对任意XML输入进行漂亮的打印格式。你需要一个程序来应用正则表达式,以查找标签、定位匹配的关闭标签(如果标签没有自我关闭),等等。使用正则表达式解决这个问题实际上是在使用错误的工具。最简单的漂亮打印XML方法是使用XML解析器,读取它,设置适当的序列化选项,然后将XML序列化输出。您为什么想使用正则表达式来解决这个问题呢?

3
使用正则表达式处理这个任务将是一场噩梦。基于节点层次结构跟踪缩进级别几乎是不可能的。也许Perl 5.10的正则表达式引擎可以帮助,因为它现在是可重入的。但我们不要走那条路……此外,您需要考虑可以嵌入需要被缩进忽略并保留原样的XML声明的CDATA部分。

坚持使用DOM。如其他答案中建议的那样,某些库已经提供了一个函数,可以为您缩进DOM树。如果没有,构建一个比创建和维护执行同样任务的正则表达式要简单得多。


2

1
this link中:
  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();
  }

1

这只能通过多个正则表达式实现,这些表达式将像状态机一样运行。

你所寻找的更适合于即兴解析器。


一个正则表达式已经是一个状态机。我非常确定这可以使用正则表达式实现(如果支持前瞻),但结果可能会相当丑陋。 - Drew Noakes
那实际上在理论上是不可能的。XML是一种无上下文语言,不能通过正则表达式(正则语言)进行缩进。请参阅乔姆斯基语言层次结构中的第3型和第2型:https://en.wikipedia.org/wiki/Chomsky_hierarchy - Hristo Vrigazov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接