Como mudar XML baseado em jogos regex para texto (dados de caracteres)
Pergunta
Eu estou tentando corresponder o conteúdo de texto (dados de caracteres) de um arquivo XML com uma série de regexs e altere o XML com base nas partidas. Exemplo:
<text>
<para>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</para>
</text>
Eu quero corresponder, por exemplo, o seguinte regex para o texto:
\bdolor.\b
Para cada jogo que eu quero, por exemplo, cercar a partida com etiquetas ou de modo semelhante acima voltas em:
<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>
Uma complicação adicional é que o texto (dados de caracteres) que eu quero para o jogo contra pode englobar várias tags.
Eu acho que o que estou tentando fazer é muito semelhante ao que um aplicativo processador de texto teria que fazer se você fizer uma pesquisa que seleciona uma parte correspondente do texto e, em seguida, por exemplo alterações na formatação do combinado / texto selecionado .
Eu gostaria de usar Java (na verdade Clojure) para fazer isso e eu pretendo usar JAXB para manipular o documento XML.
Como é que eu vou fazer acima?
Solução
EDIT:
OK, agora que eu entendo isso pode atravessar marcas que eu acho que entendo a dificuldade aqui.
O único algoritmo que eu posso pensar aqui é para percorrer a árvore XML lendo as porções de texto em busca de seu jogo - você vai precisar de fazer este personagem-se de correspondência pelo caráter em vários nós. A dificuldade, claro, é não munge a árvore no processo ...
Aqui está como eu faria isso:
Criar um andador para caminhar até a árvore XML. Sempre que você acha que encontrou o início da partida corda, salvar o que o nó pai atual. Quando (e se) você encontrar o fim do seu check seqüência de jogo se o nó salva é o mesmo que o pai do nó final. Se eles são o mesmo, então é seguro modificar a árvore.
Exemplo doc:
<doc>This is a an <b>example text I made up</b> on the spot! Nutty.</doc>
Teste 1: Jogo: exemplo de texto
O walker iria caminhar ao longo até encontrar o "e" no exemplo, e que iria salvar o nó pai (nó <b>
) e continue andando até encontrar o final de text
onde ele iria verificar para ver se ele ainda estava em o mesmo <b>
nó de referência, que é, por isso é um jogo e você pode marcá-lo com ou o que quer.
Test 2: Jogo: um exemplo
O walker iria primeiro hit a
e rapidamente rejeitá-la, em seguida, bateu an
e salvar o nó <doc>
. Ele iria continuar a corresponder mais ao texto example
até que ele percebe nó pai desse exemplo é <b>
e não <doc>
altura em que o jogo é falha e nenhum nó está instalado.
Implementação 1:
Se você só estão combinando texto em linha reta, então a correspondência simples usando um Java (SAX ou algo) parece ser uma maneira de ir aqui.
Implementação 2:
Se correspondência entrada é regex si mesmo, então você vai precisar de algo muito especial. Não sei de nenhum motor que poderia trabalhar aqui com certeza, o que você pode ser capaz de fazer é escrever um pouco de feio algo para fazê-lo ... Talvez algum tipo de walker recursiva que iria quebrar o árvore XML em cada vez menores conjuntos de nós, procurando o texto completo em cada nível ...
códigoMuito áspero (não-trabalho):
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
Uma vez que você sabe onde o nó é que deve conter o seu jogo, eu não tenho certeza do que pode fazer, porque embora você não sabe como você pode descobrir o índice dentro do texto onde é necessária a partir do regex .. . Talvez alguém tem um regex lá fora, você pode modificar ...
Outras dicas
Presumo que "o texto eu quero para o jogo contra irá abranger várias marcas" significa algo como isto:
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.
Este parece ser um problema especialmente difícil porque a transformação que você está falando pode resultar em XML que não está bem formado - por exemplo, olha o que acontece se você tentar colocar marcas ao redor do substring aqui:
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.
Para produzir uma saída bem-formado, você provavelmente precisa dele para se parecer com:
<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.
Em teoria, cada personagem que você está combinando poderia estar em um elemento diferente:
Almost like <i><u>i</u><u>n</u> </i><u>th</u>is<i><i><u> ex</i>am</i>ple.</i>
Você tem basicamente dois problemas aqui, e nem é simples:
-
Pesquisar um fluxo de XML para uma substring, ignorando tudo o que não é um nó de texto, e retornar as posições de início e fim do substring dentro do fluxo.
-
Dado dois índices arbitrários em um documento XML, criar um elemento colocando o texto entre esses índices, fechando (e reabrir) quaisquer elementos cujas marcas abrangem quer, mas não ambos dos dois índices.
É muito claro para mim que XSLT e expressões regulares não vai ajudá-lo aqui. Eu não acho que usando um DOM irá ajudá-lo aqui, também. Na verdade eu não acho que há uma resposta para o segundo problema que não envolve escrever um analisador.
Isto não é realmente uma resposta, eu sei.