
Eu tenho um problema complicado. Preciso fazer uma pequena alteração em um grande número de arquivos XML (mais de 500). A mudança envolve mudar um valor de 'falso' para 'verdadeiro'. A linha que precisa ser alterada fica assim:
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
E precisa se tornar:
<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>
Infelizmente, existem inúmeras instâncias desse conjunto de tags em cada arquivo, portanto não podemos fazer uma simples localização e substituição. O que torna esse conjunto de tags único é que elas vêm algumas linhas depois:
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
No entanto, cada arquivo tem um nome de item diferente, então usei curingas para filtrá-los.
<CID>.*BUS..*.DKV</CID>
O problema é que o número de linhas entre a parte CID e a linha que precisa ser alterada não é consistente de arquivo para arquivo. Preciso encontrar uma maneira de eliminar as linhas intermediárias e substituir a linha Size.
Alguma ideia? Eu já tentei:
<CID>.*BUS..*.DKV</CID>.*?<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>
Mas por algum motivo isso não funcionou. Agradeço antecipadamente!
Editar em resposta ao comentário:
Basicamente o que estou dizendo é que o código fica assim:
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
E outras seções do código são semelhantes a:
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
em outros lugares do código. Então estou usando a linha CID .BUS .DKV como ponto de partida. Basicamente preciso alterar a primeira ocorrência da linha SizeisMeasured que vem diretamente APÓS a linha CID .BUS .DKV. Mas há muitas outras linhas intermediárias (nenhuma das quais é consistente de arquivo para arquivo) com as quais não me importo e que estão atrapalhando minha pesquisa.
Responder1
Você pode usar lookahead negativo assim. Procurar
(?!<CID>.*BUS..*.DKV</CID>(.*?))<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
e substitua por
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
Expressão regular, correspondência. nova linha
Lookahead negativo (?!a)
e Lookbehind negativo (?<!a)
, também são chamados de Lookaround. Lookaround corresponde aos caracteres, mas desiste da correspondência, retornando apenas o resultado: correspondência ou nenhuma correspondência.
Você pode encontrar mais aqui Asserções Lookahead e Lookbehind de comprimento zero
Responder2
Analisar XML e respeitar a hierarquia com expressões regulares é desnecessariamente difícil. Eu usaria uma ferramenta completamente diferente, projetada explicitamente para o que você está tentando fazer, que é transformar XML. Estou falando de XSLT. Então, aqui está minha solução para o seu problema usando XSLT. Existem vários sites que você pode usar para converter seu XML com XSLT ou executar XSLT localmente.
O problema seria mais fácil se cada um dos seus grupos (CID seguido por SizeIsMeasuredLineLine) estivesse dentro de um único pai, mas o código abaixo analisa o primeiro irmão CID anterior para ver qual valor ele possui. Se tiver um valor correspondente à expressão regular (ITEMNAME.[^.]+.ITEMNAME..+) então ele altera o falso para verdadeiro. Todos os outros elementos são simplesmente copiados para a saída.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SizeIsMeasuredLineLine[matches(preceding-sibling::CID[1], 'ITEMNAME\.[^.]+\.ITEMNAME\..+')]">
<xsl:copy>TRUE</xsl:copy>
</xsl:template>
Aqui está o exemplo de XML que criei para testar o acima:
<?xml version="1.0" encoding="UTF-8"?>
<parent>
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.122.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.44.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.BUS.33.DKV</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
<CID>ITEMNAME.COLR.ITEMNAME.FCLR</CID>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<tag>Some Number of Other lines</tag>
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
</parent>