1

我需要合并两个 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>
...

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

可以直接添加位置数据。但是,消息应该放在 <item> 标记内,应该添加一个 <date> 标记(基于消息的 unix 时间),并且 <Message> 标记应该替换为 <m:Message type="received" > 标签。

不幸的是,这不是一个“简单”的合并,尤其是当日志文件的大小介于 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>
...

有没有支持这样合并的工具?或者有什么简单的方法可以使用java解决这个问题?

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

4

1 回答 1

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>

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

于 2012-02-03T05:13:06.970 回答