Прежде всего, я прекрасно осознаю, что пытаться писать XML-парсер вручную - ужасная идея, и что ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ ͠P̯͍̭O̚ N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ и т. Д.
Тем не менее, у меня есть задание, в котором я должен взять веб-страницу, вырезать теги (немного по-разному обрабатывать <p>
и <a href>
) и отобразить красивый текст без тегов. Мне не разрешается использовать пакет org.xml.sax или что-либо подобное.
Наш класс еще не узнал о регулярных выражениях, и большинство моих одноклассников произносят нечестивые заклинания с String.indexOf()
. Мне казалось, что намного проще (не говоря уже о том, чтобы лучше) взломать основанный на событиях парсер {X, HT} ML.
Итак, у меня есть Scanner
для потока веб-страницы, и я имею это (некоторые детали удалены для краткости):
stream.useDelimiter("\r?\n|\r"); // Use platform-independent newlines
//as delimiter
// 1 2 3 4 5 6 7 8 9 10
String tagRE = "([^<>]*?)(<!?\\s*)(/?)(\\s*)(\\w*)(\\s*[^<>]*?)(/?)(\\s*)(>)([^<>]*)";
//(Reluctant-anything) < whitespace optional-/ whitespace (word) whitespace
//reluctant-anything > (greedy-anything)
fireOpenFileEvent();
Pattern tagPat = Pattern.compile(tagRE);
while(stream.hasNextLine())
{
if(stream.hasNext(tagPat))
{
String toParse = stream.next(tagPat);
Matcher m = tagPat.matcher(toParse);
if(! m.matches()) System.err.println("Impossible non-match!");
fireTextEvent(m.group(1));
String tag = m.group(5);
if(! m.group(7).equals("")) //Self-closing tag
{
fireTagEvent(new XMLElement(tag, false));
fireTagEvent(new XMLElement(tag, true));
}
else
{
fireTagEvent(new XMLElement(tag, m.group(3).equals("/")));
}
fireTextEvent(m.group(10));
}
else //No tags (regex doesn't match). Just plain text
{
fireTextEvent(stream.nextLine);
}
}
fireEOFEvent();
Это прекрасно работает во многих случаях, кроме одного - когда в строке более одного тега. Я действительно надеялся, что Scanner
не разбьет вещи на токены - и что вызов next(pattern)
сожрет столько потока, сколько необходимо для соответствия. Таким образом, если строка была <b>Hello World!</b>
, она соответствовала бы <b>Hello World!
на одной итерации, а затем </b>
в следующий раз. Вместо этого он обрабатывает строку за раз. Поскольку вся строка не соответствует шаблону, она обрабатывается предложением else. И никакие теги не удаляются.
Так какой же самый лучший подход? Есть ли какой-то магический разделитель, который я могу использовать? Должен ли я заставить регулярное выражение сопоставлять что-либо с тегом, отрубить первый тег, а затем рекурсивно обработать остальную часть строки? Должен ли я попробовать гигантский взлом и заменить каждое "<" на "\ n <"? Я вообще не на той ноге? </p>
Заранее спасибо.