¿Fusiona dos archivos de registro XML diferentes(rastreo y mensajes) usando la fecha y la marca de tiempo?
xslt merge (1)
Esta transformación XSLT 2.0 (por conveniencia que contiene la pequeña muestra de registro de mensajes en línea):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:m="some:M" exclude-result-prefixes="xs m">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vDateU0" select="xs:dateTime(''1970-01-01T00:00:00'')"/>
<xsl:variable name="vMessages">
<Message> // some content of the message
<subTag>
<timeStamp>1342264087</timeStamp>
</subTag> // other content of the message
</Message>
<Message> // some content of the message2
<subTag>
<timeStamp>1342264089</timeStamp>
</subTag> // other content of the message2
</Message>
</xsl:variable>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="vProcessedMessages">
<xsl:apply-templates select="$vMessages/*"/>
</xsl:variable>
<xsl:variable name="vProcessedTrace">
<xsl:apply-templates select="/*/*"/>
</xsl:variable>
<xsl:perform-sort select="$vProcessedMessages/*|$vProcessedTrace/*">
<xsl:sort select="xs:dateTime(date)"/>
</xsl:perform-sort>
</xsl:template>
<xsl:template match="Message">
<xsl:variable name="vUnixDuration" select=
"concat(''PT'', */timeStamp, ''S'')"/>
<item>
<date><xsl:sequence select=
"$vDateU0 + xs:dayTimeDuration($vUnixDuration)"/>
</date>
<m:Message type="received">
<xsl:sequence select="text()[1]"/>
</m:Message>
</item>
</xsl:template>
<xsl:template match="date/text()">
<xsl:variable name="vdatePart" select="substring-before(., '' '')"/>
<xsl:variable name="vYear" select=
"substring-after(substring-after($vdatePart, ''.''), ''.'')"/>
<xsl:variable name="vMonth" select=
"substring-before(substring-after($vdatePart, ''.''), ''.'')"/>
<xsl:variable name="vDay" select="substring-before(., ''.'')"/>
<xsl:variable name="vFormattedMonth" select=
"if(string-length($vMonth) eq 1)
then concat(''0'', $vMonth)
else $vMonth
"/>
<xsl:variable name="vFormattedDay" select=
"if(string-length($vDay) eq 1)
then concat(''0'', $vDay)
else $vDay
"/>
<xsl:value-of select=
"concat($vYear,
''-'',
$vFormattedMonth,
''-'',
$vFormattedDay,
''T'',
substring-after(., '' '')
)"/>
</xsl:template>
</xsl:stylesheet>
cuando se realiza en el documento XML Trace-log proporcionado :
<items>
<item>
<date>14.7.2012 11:08:07.222</date>
<MyPosition> // Position data </MyPosition>
</item>
<item>
<date>14.7.2012 12:13:07.112</date>
<MyPosition> // Position data </MyPosition>
</item>
</items>
fusiona los dos registros según sea necesario :
<item>
<date>2012-07-14T11:08:07</date>
<m:Message xmlns:m="some:M" type="received"> // some content of the message
</m:Message>
</item>
<item>
<date>2012-07-14T11:08:07.222</date>
<MyPosition> // Position data </MyPosition>
</item>
<item>
<date>2012-07-14T11:08:09</date>
<m:Message xmlns:m="some:M" type="received"> // some content of the message2
</m:Message>
</item>
<item>
<date>2012-07-14T12:13:07.112</date>
<MyPosition> // Position data </MyPosition>
</item>
Nota : En el caso real, el mensaje de registro se obtendrá utilizando la función document()
.
Necesito unir dos archivos de registro XML. Un archivo de registro contiene un seguimiento con actualizaciones de posición. El otro archivo de registro contiene los mensajes recibidos. Puede haber múltiples mensajes recibidos sin tener una actualización de posición entre ellos.
Ambos registros tienen marcas de tiempo:
- El registro de seguimiento usa <fecha> (ej. 14.7.2012 11:08:07)
- El registro de mensajes utiliza una marca de tiempo de unix <marca de tiempo> (por ejemplo, 1342264087)
La estructura de la traza se ve así:
<item>
<date>14.7.2012 11:08:07.222</date>
<MyPosition>
// Position data
</MyPosition>
</item>
<item>
<date>14.7.2012 12:13:07.112</date>
<MyPosition>
// Position data
</MyPosition>
</item>
...
La estructura de los mensajes es así:
<Message>
// some content of the message
<subTag>
<timeStamp>1342264087</timeStamp>
</subTag>
// other content of the message
</Message>
<Message>
// same as above
</Message>
...
Al hacer la fusión, las marcas de tiempo deben leerse (también convertir / comparar "fecha" y "marca de tiempo") y todas las posiciones y mensajes agregados en el orden correcto.
Los datos de posición solo se pueden agregar tal como están. Sin embargo, el mensaje debe colocarse dentro de las etiquetas <item>, debe agregarse una etiqueta <date> (basada en el tiempo Unix de los mensajes) y la etiqueta <Message> debe reemplazarse por <m: Message type = "received" > etiquetas.
Lamentablemente, no es una fusión "simple", especialmente porque el tamaño de los archivos de registro está entre 5 MB y 700 MB ...: - /
Un resultado podría verse así:
<item>
<date>14.7.2012 11:08:07.222</date>
<MyPosition>
// Position data
</MyPosition>
</item>
<item>
<date>14.7.2012 11:09:10.867</date>
<m:Message type="received">
// content of the <Message>
</m:Message>
</item>
<item>
<date>14.7.2012 12:10:11.447</date>
<m:Message type="received">
// content of the former <Message>
</m:Message>
</item>
<item>
<date>14.7.2012 12:13:07.112</date>
<MyPosition>
// Position data
</MyPosition>
</item>
<item>
<date>14.7.2012 12:17:11.227</date>
<m:Message type="received">
// content of the former <Message>
</m:Message>
</item>
...
¿Hay alguna herramienta que soporte una fusión así? ¿O hay alguna forma simple de resolver esto usando Java?
Realmente aprecio cualquier consejo sobre cómo resolver este asunto.