xml - sacar - Crear elementos padre-hijo a partir de jerarquía semántica en valores de elementos en XSLT 2
xpath salto de linea (1)
Tengo una serie de etiquetas P en contenido XML que tienen una jerarquía semántica dentro de sus valores iniciales, sin embargo, las etiquetas P son lineales. Buscando la transformación XSLT 2.
La jerarquía semántica es la siguiente:
(1)
+-(a)
+-(I)
+-(A)
Con la secuencia de RegEx de la siguiente manera:
<xsl:param name="patternOrder" as="element(pattern)*" xmlns="">
<pattern level="1" value="^(/([0-9]+(/.[0-9]+)?/))" />
<pattern level="2" value="^(/([a-z]/))" />
<pattern level="3" value="^(/((IX|IV|V?I{{0,3}})/))" />
<pattern level="4" value="^(/([/w]+(/.[/w]+)?/))" />
</xsl>
Después de revisar mi conjunto de datos, tengo varias condiciones:
<?xml version="1.0" encoding="UTF-8"?>
<test>
<content>
<p>(1) blah</p>
<p>(2)(a) blah</p>
<p>(b) blah</p>
<p>(3)(a)(I) blah</p>
<p>(II) blah</p>
<p>(A) blah</p>
<p>(B.1) blah</p>
<p>(b) blah</p>
<p>(4) blah</p>
<p>(4.5) blah</p>
<p>(5)(a)(I)(A) blah</p>
<p>(B) blah</p>
<p>(II) blah</p>
<p>(III)(a) blah</p>
<p>(bb.2) blah</p>
<p>(6) blah</p>
</content>
<content>
<p>blah</p>
</content>
<content>
<p>blah</p>
<p>(1) blah</p>
<p>(a) blah</p>
<p>(b) blah</p>
<p>(2) blah </p>
</content>
</test>
... y los resultados finales deberían ser:
<?xml version="1.0" encoding="UTF-8"?>
<test>
<content>
<p>(1) blah</p>
<p>(2)
<p>(a) blah</p>
<p>(b) blah</p>
</p>
<p>(3)
<p>(a)
<p>(I) blah</p>
<p>(II) blah
<p>(A) blah</p>
<p>(B) blah</p>
</p>
</p>
<p>(b) blah</p>
</p>
<p>(4) blah</p>
<p>(4.5) blah</p>
<p>(5)
<p>(a)
<p>(I)
<p>(A) blah</p>
<p>(B.1) blah</p>
</p>
<p>(II) blah</p>
<p>(III)</p>
<p>(a) blah</p>
<p>(bb.2) blah</p>
</p>
</p>
<p>(6) blah</p>
</content>
<content>
blah
</content>
<content>
blah
<p>(1) blah
<p>(a) blah</p>
<p>(b) blah</p>
</p>
<p>(2) blah </p>
</content>
</test>
Tenga en cuenta la condición si la jerarquía semántica no está presente en la etiqueta P; a continuación, se elimina la etiqueta P y es un valor de su elemento de contenido primario.
EDITAR:
Pude detectar todas las condiciones semánticas usando el siguiente RegEx:
^(/(([/w]+(/.[/w]+)?)/)){1,4}
* EDIT # 2 *
Con los atributos de nivelación:
<?xml version="1.0" encoding="UTF-8"?>
<test>
<content>
<p level="1">(1) blah</p>
<p level="1">(2)</p>
<p level="2">(a) blah</p>
<p level="2">(b) blah</p>
<p level="1">(3)</p>
<p level="2">(a)</p>
<p level="3">(I) blah</p>
<p level="3">(II) blah</p>
<p level="4">(A) blah</p>
<p level="4">(B.1) blah</p>
<p level="2">(b) blah</p>
<p level="1">(4) blah</p>
<p level="1">(4.5) blah</p>
<p level="1">(5)</p>
<p level="2">(a)</p>
<p level="3">(I)</p>
<p level="4">(A) blah</p>
<p level="4">(B) blah</p>
<p level="3">(II) blah</p>
<p level="3">(III)</p>
<p level="2">(a) blah</p>
<p level="2">(bb.2) blah</p>
<p level="2">(6) blah</p>
</content>
<content>
<p>blah</p>
</content>
<content>
<p>blah</p>
<p level="1">(1) blah</p>
<p level="2">(a) blah</p>
<p level="2">(b) blah</p>
<p level="1">(2) blah </p>
</content>
</test>
Primera fase: transformar
<p>(2)(a) blah</p>
<p>(b) blah</p>
dentro
<p>(2)</p>
<p>(a) blah</p>
<p>(b) blah</p>
usando algo como
<xsl:template match="p">
<xsl:for-each select="tokenize(., ''/('')">
<xsl:if test="normalize-space(.)">
<p>(<xsl:value-of select="."/></p>
</xsl:if>
</xsl:for-each>
</xsl:template>
Segunda fase:
Primero escribe una función
<xsl:function name="f:level" as="xs:integer">
<xsl:param name="p" as="element(p)"/>
....
</xsl:function>
que calcula el "nivel semántico" basado en la coincidencia de sus expresiones regulares. Parece que sabes cómo hacer esta parte.
Luego, escribe una función de agrupación recursiva:
<xsl:function name="f:group" as="element(p )*">
<xsl:param name="in" as="element(p )*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$in" group-starting-with="p[f:level(.)=$level]">
<p><xsl:value-of select="current-group()[1]"/>
<xsl:sequence select="f:group(current-group()[position() gt 1], $level+1)"/>
</p>
</xsl:for-each-group>
</xsl:function>
y llame a esta función de esta manera:
<xsl:template match="content">
<xsl:sequence select="f:group(p, 1)"/>
</xsl:template>
No probado.