我正在处理一些包含日志记录的超大型XML文件。我有多个具有不同参数的XML文件,尽管始终存在<record>
,<date>
和<message>
标签。
它们看起来像这样(非常简化):
data1.xml:
<record>
<date>2018-10-01 00:00:00</date>
<message>data1</message>
<param key="Key1">Info</param>
<param key="Key2">Info</param>
<param key="Key3">Info</param>
</record>
<record>
<date>2018-10-02 00:00:00</date>
<message>data1</message>
<param key="Key1">Info</param>
<param key="Key2">Info</param>
<param key="Key3">Info</param>
</record>
data2.xml:
<record>
<date>2018-10-01 00:00:00</date>
<message>data2</message>
<param key="Key4">Info</param>
<param key="Key5">Info</param>
</record>
<record>
<date>2018-10-02 00:00:00</date>
<message>data2</message>
<param key="Key6">Info</param>
<param key="Key7">Info</param>
</record>
data3.xml:
<record>
<date>2018-10-01 00:00:00</date>
<message>data3</message>
<param key="Duration(h)">0:00:10</param>
<attribute1>Info</attribute1>
</record>
<record>
<date>2018-10-02 00:00:00</date>
<message>data3</message>
<param key="Duration(h)">0:01:30</param>
<attribute1>Info</attribute1>
</record>
我正在使用XSLT根据多个变量过滤记录,例如,可能是日期和消息,或者消息和key1等,等等。
在XSLT内,我要做的就是过滤出所需的记录,并调用<xsl:apply-imports>
以拥有一系列其他XSLT文件,这些文件可以管理诸如对输出进行排序,格式化和其他操作。 >
我目前正在过滤所需的XML节点,如下所示:
在此示例中,假设我想要包含<message>data1</message>
和<message>data3</message>
的记录,并编辑它们的属性以将它们很好地显示在表中。
filter1.xsl:
<!-- ignores records not matched by another template, so in this case 'data2' -->
<xsl:template match="record" />
<!-- applies imports to 'wanted' data -->
<xsl:template match="record[message='data1']">
<xsl:apply-imports />
</xsl:template>
<!-- applies imports to 'wanted' data -->
<xsl:template match="record[message='data3']">
<xsl:apply-imports />
</xsl:template>
<!-- rename 'param' to match the attribute from 'data3.xml' -->
<xsl:template match="param[@key='key1']">
<xsl:copy>
<xsl:attribute>attribute1</xsl:attribute>
<xsl:value-of select="." />
</xsl:copy>
</xsl:template>
到目前为止,一切都很顺利。
“ data3.xml”中的每条记录都标志着操作的结束,因此是“ duration”参数。我想复制每个节点以标记此操作的开始。
所以输入:
<!-- marking end of operation -->
<record>
<date>2018-10-01 00:00:00</date>
<message>data3</message>
<param key="Duration(h)">0:00:10</param>
<attribute1>Info</attribute1>
</record>
我想要输出:
<!-- marking start of operation -->
<record>
<date>2018-09-30 23:59:50</date>
<message>data3</message>
<attribute1>Info</attribute1>
</record>
<!-- marking end of operation -->
<record>
<date>2018-10-01 00:00:00</date>
<message>data3</message>
<param key="Duration(h)">0:00:10</param>
<attribute1>Info</attribute1>
</record>
但是我还没有找到如何复制整个节点并处理它们的方法。到目前为止,这是我尝试过的:
调用命名模板以基于现有节点属性创建新节点,这根本没有插入任何节点:
<xsl:template match="record[message='data3']">
<xsl:call-template name="duplicateNode"></xsl:call-template>
<xsl:apply-imports />
</xsl:template>
<xsl:template name="duplicatePrintedNode">
<xsl:copy>
<record>
<date>2018-09-30 23:59:50</date>
<message>data3</message>
<attribute1>Info</attribute1>
</record>
</xsl:copy>
</xsl:template>
使用<xsl:copy-of value"">
复制整个节点。这似乎是在要复制的现有节点的属性的内部中插入一个节点:
<xsl:template match="param[@key='Duration(h)']" mode="copy">
<record>
<xsl:copy>
<xsl:copy-of select="@*"/>
</xsl:copy>
</record>
</xsl:template>
那么我该如何复制节点,更改属性,然后将模板应用于它们并导入它们?
我在SO和Google上进行了大量搜索,但是关键字copy
在XSLT上下文中似乎具有多种含义。任何帮助将不胜感激。
答案 0 :(得分:1)
考虑以下(很多)简化示例:
XML
$(this)
XSLT 1.0
<input>
<record>
<date>2018-10-01 00:00:00</date>
<message>data3</message>
<param key="Duration(h)">0:00:10</param>
<attribute1>Info</attribute1>
</record>
</input>
结果
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/input">
<output>
<xsl:apply-templates/>
</output>
</xsl:template>
<xsl:template match="record[message='data3']">
<xsl:copy>
<date>new value</date>
<xsl:copy-of select="node()[not(self::date or self::param)]"/>
</xsl:copy>
<xsl:copy>
<xsl:copy-of select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
注意:出于演示的目的,我使用了<?xml version="1.0" encoding="UTF-8"?>
<output>
<record>
<date>new value</date>
<message>data3</message>
<attribute1>Info</attribute1>
</record>
<record>
<date>2018-10-01 00:00:00</date>
<message>data3</message>
<param key="Duration(h)">0:00:10</param>
<attribute1>Info</attribute1>
</record>
</output>
而不是xsl:copy-of
-因为我们不知道这些进口是什么。
答案 1 :(得分:0)
我找到了一种方法,我意识到这样做的教育价值非常低,因为我的情况是如此具体,但是无论如何我都会发布它。也要感谢@ michael.hor257k的帮助。
我复制特定节点并对两个节点应用导入的方式是:
filter1.xsl
<script>
$(document).ready(function() {
$("div.text-center").css("color", "red");
});
</script>