使用日期和时间戳合并两个不同的XML日志文件(跟踪和消息)?

时间:2012-02-02 17:03:20

标签: xml xslt merge timestamp logfiles

我需要合并两个XML日志文件。一个日志文件包含具有位置更新的跟踪。另一个日志文件包含收到的消息。可以有多个收到的消息,而不会在两者之间进行位置更新。

两个日志都有时间戳:

  • 跟踪日志使用< date> (例如,14.7.2012 11:08:07)
  • 消息日志使用unix时间戳< timeStamp> (例如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>
...

在进行合并时,应该读取时间戳(也可以转换/比较“日期”和“时间戳”)以及按正确顺序添加的所有位置和消息。

位置数据可以按原样添加。但是,邮件应放在&lt; item&gt;内。标签,一个&lt; date&gt;应添加标签(基于消息的unix时间)和&lt; Message&gt;标签应替换为&lt; m:消息类型=“已收到”&gt;标签

不幸的是,不是“简单”的合并,特别是当日志文件的大小介于5 MB和700 MB之间时......: - /

结果可能如下所示:

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

是否有支持合并的工具?或者有没有简单的方法来解决这个问题?

我非常感谢有关如何解决此事的任何提示。

1 个答案:

答案 0 :(得分:1)

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

在提供的跟踪日志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()函数获取消息日志。