
Tengo un problema complicado. Necesito hacer un cambio menor en una gran cantidad de archivos xml (más de 500). El cambio implica cambiar un valor de "falso" a "verdadero". La línea que necesita cambiar se ve así:
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
Y debe convertirse en:
<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>
Lamentablemente, existen numerosas instancias de este conjunto de etiquetas en cada archivo, por lo que no podemos realizar una simple búsqueda y reemplazo. Lo que hace que este conjunto de etiquetas sea único es que aparecen algunas líneas después:
<CID>ITEMNAME.BUS.ITEMNAME.DKV</CID>
Sin embargo, cada archivo tiene un nombre de elemento diferente, por lo que utilicé comodines para filtrarlos.
<CID>.*BUS..*.DKV</CID>
El problema es que la cantidad de líneas entre la parte CID y la línea que necesita cambiar no es consistente de un archivo a otro. Necesito encontrar una manera de eliminar las líneas intermedias con comodines y reemplazar la línea Tamaño.
¿Algunas ideas? Ya lo he probado:
<CID>.*BUS..*.DKV</CID>.*?<SizeIsMeasuredLineLine>true</SizeIsMeasuredLineLine>
Pero por alguna razón eso no funcionó. ¡Gracias de antemano!
Editar en respuesta al comentario:
Básicamente lo que digo es que el código se ve así:
<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>
Y otras secciones del código se ven así:
<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>
en otros lugares del código. Entonces estoy usando la línea CID .BUS .DKV como punto de partida. Básicamente necesito cambiar la primera aparición de la línea SizeisMeasured que viene directamente DESPUÉS de la línea CID .BUS .DKV. Pero hay muchas otras líneas intermedias (ninguna de las cuales es consistente de un archivo a otro) que no me importan y que están arruinando mi búsqueda.
Respuesta1
Puedes utilizar una anticipación negativa como esta. Buscar
(?!<CID>.*BUS..*.DKV</CID>(.*?))<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
y reemplazar con
<SizeIsMeasuredLineLine>false</SizeIsMeasuredLineLine>
Expresión regular, coincidencia. nueva línea
Lookahead negativo (?!a)
y Lookatherback negativo (?<!a)
, también se denominan Lookaround. Lookaround coincide con los caracteres, pero luego abandona la coincidencia y solo devuelve el resultado: coincidencia o no coincidencia.
Puedes encontrar más aquí Afirmaciones de longitud cero anticipadas y retrospectivas
Respuesta2
Analizar XML respetando la jerarquía con expresiones regulares es innecesariamente difícil. Yo usaría una herramienta completamente diferente que esté diseñada explícitamente para lo que estás intentando hacer, que es transformar XML. Estoy hablando de XSLT. Entonces, aquí está mi solución para su problema al usar XSLT. Existen varios sitios web que puede utilizar para convertir su XML con XSLT, o puede ejecutar XSLT localmente.
El problema sería más fácil si cada uno de sus grupos (CID seguido de SizeIsMeasuredLineLine) estuviera dentro de un solo padre, pero el siguiente código analiza el primer hermano CID anterior para ver qué valor tiene. Si tiene un valor que coincide con la expresión regular (ITEMNAME.[^.]+.ITEMNAME..+), entonces cambia falso a verdadero. Todos los demás elementos simplemente se copian en la salida.
<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>
Aquí está el XML de muestra que creé para probar lo anterior:
<?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>