2009-03-20 3 views
0

Я получаю некоторые данные html с удаленного сервера и перед отображением его в пользовательском интерфейсе приложения мне нужно внести некоторые изменения, то есть удалить счетчики, заменить ссылки и т. Д. Удаление некоторых тегов с содержимым и изменение конкретной ссылки не имеет большого значения, но когда дело доходит до некоторой передовой обработки, у меня есть некоторые проблемы. Необходимо заменить (удалить) несколько атрибутов тега html (не сам тег - есть много примеров по интернету о это). Например: удалить все обработчики onmouseover с помощью кнопок. Я знаю, что XPath будет идеально подходит для такой проблемы, но я вообще этого не знаю, и хотя моя информация - жалоба XHTML, она хранится в строковой переменной и не запрашивается :(. Поэтому я пытаюсь использовать Регулярные выражения, чтобы решить эту проблему, не имела успеха на данный момент. Я думаю, что это ошибка в шаблоне ...C# - Обработка атрибутов тегов html

public string Processing (string Source, string Tag, string Attribute) 
{  
return System.Text.RegularExpressions.Regex.Replace(Source, string.Format(@"<{0}(\s+({1}=""([^""]*)""|\w+=(""[^""]*""|\S+)))+>", Tag, Attribute), string.Empty); 
} 

... 

string before = @"<input type=""text"" name=""Input"" id=""Input"" onMouseOver=""some js to be eliminated"">"; 
string after = Processing(before,"input","onMouseOver"); 
// expected : <input type="text" name="Input" id="Input">" 

ответ

1

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

@"(<{0}\b[^>]*?\b){1}=""(?:[^""]*)""" 

Затем вы используете «$ 1» в качестве замены строки заткнуть назад во всем, кроме атрибута.

Этот подход требует от вас сделать отдельный проход по строке для каждой из ваших целевых пар тегов/атрибутов, а в начале каждого прохода вам необходимо создать и скомпилировать регулярное выражение. Не очень эффективно, но если строка не слишком велика, все должно быть в порядке. Гораздо большая проблема заключается в том, что он не будет извлекать повторяющиеся атрибуты; если на кнопке есть два атрибута onmouseover, вы поймаете только первый.

Если бы я делал это в C#, я бы, вероятно, использовал регулярное выражение для соответствия целевому тегу, а затем используйте MatchEvaluator для одновременного удаления всех целевых атрибутов. Но если серьезно, если строка действительно представляет собой хорошо сформированный XML, нет никаких оправданий для того, чтобы не использовать инструменты, специфичные для XML, для ее обработки - это то, что XML был изобрел для.

+0

Кажется, что закрывающая круглая скобка группы отсутствует (регулярное выражение не компилируется). Исправлено выражение: @ "(<{0}\b[^>] *? \ B) ({1} =" "(?: [^" "] *)" ")" – Jaded

+0

И, конечно же, спасибо большое, ваш намек на самом деле мне было нужно. – Jaded

+0

Упс. На самом деле, открывающий круглый кронштейн перед {1} не должен быть там. Нет смысла захватывать атрибут, поскольку все, что вы делаете, это его удаление. –

1

Я знаю, это вопрос о том (крепление) RegEx, но альтернативный подход заключается в загрузке вашего Xhtml в XmlDocument (он принимает строку) или XDocument и использует XPath или Linq.

+0

Ну, я бы оценил простой пример XPath;) – Jaded

0

Я думаю, что ваш подход слишком упрощен. Разбор HTML с использованием регулярных выражений может быть намного сложнее, чем вы думаете. Я бы предложил вы взять look at this question.

+0

Используя некоторые рамки третьей стороной для такого. задача будет «намного больше». Я знаю, что HTML Agility Pack достаточно мощный, b Я попытаюсь использовать его, если это действительно необходимо. – Jaded

0

Я знаю, что XPath бы идеально подходит для такой задачи

Совершенно верно. Или любой другой метод парсера XML, например методы DOM.

Это действительно не сложно научиться: наполните свою строку в методе XmlDocument.LoadXml(), затем вызовите selectNodes() на ней с чем-то вроде // // tagname [@attrname] ', чтобы получить список элементов с нежелательным атрибутом. Peasy.

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

Что с регулярными выражениями? Люди продолжают использовать их, даже когда они знают, что это неправильно, хотя они часто не читаются и трудно получить право (как бесконечное «почему мое регулярное выражение не работает?»).

Так что же такого привлекательного в отношении проклятых вещей? Есть несколько вопросов о SO каждый день о разборе [X] [HT] ML с регулярным выражением, все ответили «не использовать регулярное выражение, регулярное выражение недостаточно мощно для анализа HTML». Но почему-то это никогда не пройдет.

Я думаю, что это ошибка в шаблоне ...

Ну картина, кажется, пытается сопоставить целые теги заменить пустой строкой, которая является не то, что вы хотите. Вместо этого вы хотите настроить таргетинг только на атрибут, а затем, чтобы подсчитать только атрибуты внутри тега «< ...», вам придется использовать отрицательное утверждение lookbehind - «(?! < tag)». Но вы обычно не можете иметь утверждение lookbehind с переменной длиной, которое вам нужно, чтобы другие атрибуты попадали между именем тега и целевым атрибутом.

Также ваша статья «\ S +» может сожрать большое количество непреднамеренного содержимого. Поскольку у вас хорошо сформированный XHTML, вы гарантированно правильно цитировали атрибуты, поэтому вам это не нужно.

Но ошибка не в шаблоне. Это регулярное выражение.

+0

Несомненно. Regex полезны для многих проблем. Но если вопросы о SO - что-то в этом роде - и, судя по количеству ужасов в реальном мире, которые я видел, они, вероятно, - большинство использования регулярных выражений совершенно неуместно. – bobince

+0

Ну ... Я думал, что регулярные выражения лучше, чем что-то: Source.Substring (Source.IndexOf (Attribute), Attribute.Length + ParameterLength) или что-то еще ... Плюс документ, с которым я работаю, не полностью жалоба XHTML. Он содержит пространство имен xml, но не выполняет проверку. – Jaded

+0

«Валидация» не важна для обработки XML, она должна быть «хорошо сформирована». В противном случае существуют синтаксические анализаторы HTML, такие как пакет Agility Pack, которые все еще намного проще, чем пытаться вырвать регулярное выражение. – bobince

0

Итак, переписанный код:

public static string Process(string Source, string Tag, string Attribute) 
{ 
     return Regex.Replace(Source, string.Format(@"(<{0}\b[^>]*?\b)({1}=""(?:[^""]*)"")", Tag, Attribute), "$1");     
} 

Я проверил его, и он работает отлично.

string before = @"<input type=""text"" name=""Input"" id=""Input"" onMouseOver=""some js to be eliminated1""/>" 
     + "\r\n" + @"<input type=""text"" name=""Input2"" id=""Input2"" onMouseOver=""some js to be eliminated2"">" 
     + "\r\n" + @"<input type=""text"" name=""Input3"" id=""Input3"" onMouseOver=""some js to be eliminated3"">";    
string after = Process(before, "input", "onMouseOver"); 
//<input type="text" name="Input" id="Input" /> 
//<input type="text" name="Input2" id="Input2" > 
//<input type="text" name="Input3" id="Input3" > 

В настоящий момент проблема решена. Я бы попытался использовать обходное решение, связанное с xml, но похоже, что перед созданием XmlDocument мне нужно снова переработать входной html, потому что согласно w3c validator у него есть ошибки. Она начинается следующим образом

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
    <HTML xmlns="http://www.w3.org/1999/xhtml"> 
    <HEAD> 
    <TITLE>page title</TITLE> 

На LoadXml я получаю «System.Xml.XmlException о„>“маркер не приемлемо - линия 1 позиция 63. Добавление определение типа документа вызывает такое же исключение, но на этот раз о«- .? 'маркер неправильно, „>“ ожидается

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
     "http://www.w3.org/TR/html4/strict.dtd"> 

Любые идеи, или отпустить)

+0

Если в верхнем регистре написано , это не XHTML - возможно, более подходящим является оригинал legacy-HTML doctype, а «xmlns» - это просто ложь. – bobince

+0

(И мы не можем видеть это из введенного сообщения, но ошибка об «-» обычно является признаком разбитого комментария, такого как «». , что является недопустимым как в HTML, так и в XHTML, но будет обработано браузерами и пакетом Agility. – bobince

Смежные вопросы