Объединить два разных файла журнала XML (трассировка и сообщения), используя дату и время? - PullRequest
1 голос
/ 02 февраля 2012

Мне нужно объединить два файла журнала XML. Один файл журнала содержит трассировку с обновлениями позиции. Другой файл журнала содержит полученные сообщения. Может быть несколько полученных сообщений без обновления позиции между ними.

Оба журнала имеют метки времени:

  • В журнале трассировки используется (например, 14.7.2012 11:08:07)
  • В журнале сообщений используется метка времени Unix (например, 1342264087)

Структура трассы выглядит следующим образом:

<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>
...

Структура сообщений такая:

<Message>
    // some content of the message
    <subTag>
        <timeStamp>1342264087</timeStamp>
    </subTag>
    // other content of the message
</Message>
<Message>
    // same as above
</Message>
...

При объединении следует читать метки времени (также конвертируя / сравнивая «дату» и «метку времени»), а все позиции и сообщения добавляя в правильном порядке.

Данные о местоположении могут быть просто добавлены как есть. Однако сообщение должно быть помещено в теги , тег должен быть добавлен (в зависимости от времени unix сообщений), а тег должен быть заменен на теги.

К сожалению, это не "простое" объединение, особенно если размер файлов журнала лежит в диапазоне от 5 до 700 МБ ...: - /

Результат может выглядеть так:

<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>
...

Существуют ли инструменты, которые поддерживают такое объединение? Или есть какой-нибудь простой способ решить эту проблему с помощью Java?

Я очень ценю любые советы о том, как решить эту проблему.

1 Ответ

1 голос
/ 03 февраля 2012

Это преобразование XSLT 2.0 (для удобства содержит небольшой встроенный образец журнала сообщений):

<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>

при выполнении с предоставленным документом Trace-log XML :

<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>

объединяет два журнала в соответствии с требованиями :

<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>

Примечание : В реальном случае журнал сообщений будет получен с использованием функции document().

...