2013-03-23 4 views
1

Я хотел бы удалить все атрибуты из моей структуры XML. Мой выбор - это регулярное выражение, но если есть более простой способ, я широко открыт для предложений.Как очистить XML-атрибуты с помощью regex?

Чтобы выбрать один, исправить тег, я использовал следующее.

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). Ничто не убирается, или все. Что я делаю неправильно?

Я заметил, что изменение начала для плюса дает мне теги, которые содержат только первую букву имен, поэтому я уверен, что следующий путь - это правильный путь, пока я могу сделать выбранный up для $ 1 максимально большой. Как мне это сделать?

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

Пожалуйста, не используйте Regex для чего-либо связанного XML. Есть много лучших решений. –

+0

Упомяните о трех из них в порядке убывания популярности и уместности? – 2013-03-23 23:00:39

+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>"); 
+0

Правильно ... Как это исправить? – 2013-03-23 23:03:54

+0

Не нужно '?', И почему он должен обрабатывать закрывающий тег? – MikeM

+0

Возможно, я ошибся. Когда я тестировал сначала, я получил это, чтобы потерпеть неудачу на ленивой оценке. Но кажется, что ты прав. Спасибо что подметил это. Заключить тег нужно обрабатывать или вы получите пустой тег, не так ли? Во всяком случае, последнее предлагаемое регулярное выражение делает работу, похоже. –

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; 
      } 
     } 
    } 
} 
+0

Хотя я согласен, что регулярное выражение является злым и его вряд ли можно использовать, в этом конкретном примере он предлагает решение одной строки кода. * XDocument * пример нужен прокрутка ... :) –

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); 
} 
Смежные вопросы