2009-06-23 3 views
0

Я пытаюсь сопоставить текстовое содержимое (символьные данные) XML-файла с рядом регулярных выражений, а затем изменить XML на основе совпадений. Пример:Как изменить XML на основе совпадений регулярных выражений с текстом (символьные данные)

<text> 
<para>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
</para> 
</text> 

Я хочу, чтобы соответствовать, например, следующее регулярное выражение к тексту:

\bdolor.\b 

Для каждого матча я хочу, например, окружают матч с тэгами или подобными так выше превращается в:

<text> 
<para>Lorem ipsum <bold>dolor<bold/> sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et <bold>dolore<bold/> magna aliqua. 
</para> 
</text> 

Еще одно осложнение состоит в том, что текст (символьные данные), который я хочу сопоставить, может охватывать несколько тегов.

Я предполагаю, что то, что я пытаюсь сделать, очень похоже на то, что приложение текстового редактора должно будет делать, если вы выполняете поиск, который выбирает соответствующую часть текста, а затем, например, меняет форматирование согласованного/выбранного текст.

Я хотел бы использовать Java (на самом деле Clojure) для этого, и я намерен использовать JAXB для управления XML-документом.

Как мне сделать сверху?

+4

отлично, звучит так, как будто вы его поняли. в чем вопрос? –

+2

Почему бы вам просто не использовать XLST, это именно то, что было предназначено для этого. –

+0

Вы просите больших проблем, пытаясь разобрать XML с помощью регулярных выражений. Ник прав: используйте XSLT, а затем примените вашу замену к тексту элемента. –

ответ

2

EDIT:

OK теперь, когда я понимаю, это может пойти по тэгам Я думаю, что я понимаю трудность здесь.

Единственный алгоритм, который я могу здесь придумать, - это пройти дерево XML, читающее текстовые фрагменты, которые ищут ваш матч, - вам нужно будет сделать это, сопоставляя себя персонажем символом через несколько узлов. Трудность, конечно, не munge дерева в процессе ...

Вот как я бы это сделать:

Создать ходунки ходить к дереву XML. Всякий раз, когда вы думаете, что нашли начало совпадения строк, сохраните все текущие родительские узлы. Когда (и если) вы найдете конец своего совпадения строк, проверьте, совпадает ли сохраненный узел с родителем конечного узла. Если они одинаковы, тогда можно безопасно модифицировать дерево.

Пример док:

<doc>This is a an <b>example text I made up</b> on the spot! Nutty.</doc> 

Тест 1: Match: Пример текста

Ходок будет идти вперед, пока он не найдет «е» в примере, и было бы сохранить родительский узел (<b> узел) и продолжайте идти до тех пор, пока не найдет конец text, где он будет проверять, был ли он все еще в том же ссылочном узле <b>, что и есть, поэтому он является совпадением, и вы можете пометить его или что-то еще.

Тест 2: Match: пример

Ходок будет первым ударил a и быстро отклонить его, а затем нажмите an и сохранить <doc> узел. Он будет продолжать соответствовать тексту example до тех пор, пока он не осознает, что родительский узел этого примера равен <b>, а не <doc>, после чего совпадение не выполнено и ни один узел не установлен.

Осуществление 1:

Если вы только соответствующие прямой текст, то простая согласовань с помощью Java (SAX или что-то), кажется, как способ пойти сюда.

Осуществление 2:

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

Очень грубый (нерабочий) код:

def search(raw, regex): 
    tree = parseXml(raw) 
    text = getText(tree) 
    if match(text, regex): 


def searchXML(tree, regex): 
    text = getFlatText(tree) 
    if match(text, regex): # check if this text node might match 
     textNodes = getTextNodes(tree) 
     for (tn : textNodes): # check if its contained in a single text node 
      if match(tn, regex): 
       return tn 
     xmlnodes = getXMLNodes(tree) 
     for (xn : xmlnodes): # check if any of the children contain the text 
      match = searchXML(xn, regex) 
      if match 
       return match 
     return tree # matches some combination of text/nodes at this level 
        # but not at a sublevel 
    else: 
     return None # no match in this subtree 

После того, как вы знаете, где узел, который должен содержать ваш матч, I» m не уверен, что может сделать, потому что вы не знаете, как вы можете определить индекс внутри текста, где это необходимо из регулярного выражения ... Возможно, у кого-то есть регулярное выражение, которое вы можете изменить ...

+1

Моя проблема в том, что текст, который я хочу сопоставить, будет охватывать несколько тегов. Извлечение текста и объединение его вместе не проблема, и поиск начала и индекса соответствия (es) тоже не является, а возврат к XML и вставка начальных и конечных тегов в нужные места - в середине символьных данных - есть. – mac

0

я считать, что «текст я хочу, чтобы соответствовать против будет охватывать несколько тегов» означает что-то вроде этого:

In <i>this</i> example, I want to match "In this example". 

In <i><b>this</b></i> example, I also want to match "In this example". 

And <i>in <b>this</b></i> example, it's clear I have to ignore case too. 

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

In this <i>example, putting tags around "in this example"</i> will break things. 

<i>And in this</i> example, you have a similar problem. 

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

<bold>In this <i>example</i><bold><i>, putting tags around "in this example"</i> will break things. 

<i>And <bold>in this</bold></i><bold> example</bold>, you have a similar problem. 

В теории, каждый символ вы сопоставления может быть в другом элементе:

Almost like <i><u>i</u><u>n</u> </i><u>th</u>is<i><i><u> ex</i>am</i>ple.</i> 

у вас есть в основном две проблемы здесь, и ни один не просто:

  1. Поиск потока XML для подстроки, игнорирование всего, что не является текстовым узлом, и вернуть начальную и конечную позиции подстроки в потоке.

  2. Учитывая два произвольных индекса в документе XML, создайте элемент, содержащий текст между этими индексами, закрывая (и повторно открывая) любые элементы, чьи теги охватывают оба, но не оба этих индекса.

Мне совершенно ясно, что XSLT и регулярные выражения вам не помогут. Я не думаю, что использование DOM поможет вам и здесь. На самом деле я не думаю, что есть ответ на вторую проблему, которая не связана с написанием парсера.

Это не совсем ответ, я знаю.

+0

Спасибо за ваши мысли. По крайней мере, я знаю, что мой вопрос дешифрует :-). Мне пришло в голову, что операция очень похожа на то, что приложение текстового процессора должно будет делать, если вы выполняете поиск, который выбирает соответствующую часть текста, а затем, например, меняет форматирование согласованного/выделенного текста. – mac

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

  • Нет связанных вопросов^_^