如何使用正则表达式清理XML属性?

时间:2013-03-23 22:44:45

标签: c# xml regex

我想从XML结构中删除所有属性。我的选择是正则表达式,但如果有一种更简单的方法,我会大开眼界寻求建议。

要选择一个修复标记,我使用了以下内容。

String clean = Regex.Replace(filled, ".*?<holder[^>]*?>(.*?)</holder>.*?", "$1");

这给了我标签持有者的内容。我现在想保留文本质量,但省略内部标记中的所有属性。我尝试了以下方法。

String plain1 = Regex.Replace(clean, "(<[^>]*?>)(.*?)(</[^>]*?>)", "$1$2$3");
String plain2 = Regex.Replace(clean, "(<[a-zA-Z]*?)([^>]*?)(>)", "$1$3");

但它给了我相同的东西( plain1 ),只是没有原始名称的空标签( plain2 )。什么都没有得到清理或一切都是。我做错了什么?

我注意到更改plus的开头,给我的标签只包含名字的第一个字母,所以我很确定以下是正确的方法,只要我能把它拿起来 $ 1 的部分最大。我该怎么做?

String plain3 = Regex.Replace(clean, "(<[a-zA-Z]+?)([^>]*?)(>)", "$1$3");

3 个答案:

答案 0 :(得分:2)

您需要跳过第一个括号中的问号。

String plain3 = Regex.Replace(clean, "(<[a-zA-Z]+)([^>]*?)(>)", "$1$3");

一些观察结果。

  • 您需要处理结束标记。你现在正在跳过斜线角色。
Regex.Replace(clean, "(<[/a-zA-Z]+)([^>]*?)(>)", "$1$3");
  • 您无需 $ 2 。不是 $ 3 ,不是。
Regex.Replace(clean, "(<[a-zA-Z]+)[^>]*?>", "$1>");
  • 有更好的方式在正则表达式中表达“只有字母”。
Regex.Replace(clean, @"(<[\w]+)([^>]*?)(>)", "$1$3");

所以最后,你可能会得到以下结论。

Regex.Replace(clean, @"(<[/\w]*)[^>]*?>", "$1>");

答案 1 :(得分:2)

  

我的选择是正则表达式,但如果有更简单的方法,我会大开眼界寻求建议。

我猜你已经知道了this不要尝试使用正则表达式解析xml / html ,使用真正的xml解析器来处理xmls

我将使用Linq To XML。借助递归函数可以轻松完成它

var xDoc = XDocument.Load(fileName1);
RemoveAttributes(xDoc.Root);
xDoc.Save(fileName2);

void RemoveAttributes(XElement xRoot)
{
    foreach (var xAttr in xRoot.Attributes().ToList())
        xAttr.Remove();

    foreach (var xElem in xRoot.Descendants())
        RemoveAttributes(xElem);
}

答案 2 :(得分:1)

请不要使用正则表达式。

下面是如何使用纯XML实现它的示例(前半部分只是控制台内容,您需要的方法是ProcessNode):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

internal static class Program
{
    public static void Main(string[] args)
    {
        var xmlFile = XElement.Load(@"c:\file.xml"); // Use your file here
        var blockquote = xmlFile.XPathSelectElement("/");

        var doc = new XDocument();
        doc.Add(new XElement("root"));
        var processedNodes = ProcessNode(blockquote);
        foreach (var node in processedNodes)
        {
            doc.Root.Add(node);
        }

        var sb = new StringBuilder();
        var settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        settings.Encoding = Encoding.UTF8;
        settings.Indent = true;
        using (var sw = XmlWriter.Create(sb, settings))
        {
            doc.WriteTo(sw);
        }

        Console.OutputEncoding = Encoding.UTF8;
        Console.WriteLine(sb);
    }

    private static IEnumerable<XNode> ProcessNode(XElement parent)
    {
        foreach (var node in parent.Nodes())
        {
            if (node is XText)
            {
                yield return node;
            }
            else if (node is XElement)
            {
                var container = (XElement)node;
                var copy = new XElement(container.Name.LocalName);
                var children = ProcessNode(container);
                foreach (var child in children)
                {
                    copy.Add(child);
                }
                yield return copy;
            }
        }
    }
}