xml - XSLT 复制节点和更改属性
问题描述
我正在处理一些包含日志记录的非常大的 XML 文件。我有多个具有不同参数的 XML 文件,尽管<record>
,<date>
和<message>
标记始终存在。
它们看起来像这样(非常简化):
数据1.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>
数据2.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>
数据3.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>
,并编辑它们的属性以在表格中很好地显示它们。
过滤器1.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 上下文中具有多种含义。任何帮助将不胜感激。
解决方案
考虑以下(非常)简化的示例:
XML
<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>
XSLT 1.0
<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
了xsl:apply-imports
- 因为我们不知道这些导入是什么。
推荐阅读
- javascript - D3 回调函数的 `this` 遮蔽了对象的 `this`
- swift - 如何在 Vapor 3 中配置 Fluent/MySQL 数据库连接而不将密码放入 configure.swift 中?
- python - 有没有办法用 argparse 制作“隐藏”帮助菜单?
- android - 当它检测到我们之前已经使用过这个应用程序时,以新用户身份重新安装应用程序
- php - Laravel:无法运行工匠配置:缓存
- java - 在 docker 容器运行期间无法找到或加载主类 Platform
- json - 用用户json映射多个地址反应js
- azure - Azure 中的目录审核日志中缺少 odata.type
- javascript - 承诺在 vscode 中异步/等待
- python - 条纹:将无效状态设置为发票