xml - 在 XSLT 版本 1 中是否可以通过键连接 2 个 xml 文件但输入中没有它们?
问题描述
假设我们有 2 个 XML 文件 a.xml:
<Reports>
<Fields>
<PositionID>000101</PositionID>
<Date>2021-04-19</Date>
<Name>XXX</Name>
</Fields>
<Fields>
<PositionID>000100</PositionID>
<Date>2021-04-19</Date>
<Name></Name>
</Fields>
</Reports>
和 b.xml:
<AOID>
<Employee>
<Name>YYY</Name>
<PositionID>000100</PositionID>
</Employee>
<Employee>
<Name>XXX</Name>
<PositionID>000101</PositionID>
</Employee>
</AOID>
我正在寻找一个 v1 xslt,它将通过 PositionID 加入两个提取,并从 xml b 添加 Name 字段,如果它是空的或在 XML a 中不存在。
我遇到的问题是这些都不是输入,而是我将它们放在如下变量中:
<xsl:variable name="ExtractA" select="document('a.xml')" /> <xsl:variable name="ExtractB" select="document('b.xml')" />
不幸的是,我无法让它在 xslt v1 中工作,但由于我使用的平台的一些限制,我需要它。
我在 v3 xslt 中有一个工作示例用于测试,所以我需要 v1 中的相同功能:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:variable name="ExtractA">
<Reports>
<Fields>
<PositionID>000101</PositionID>
<Date>2021-04-19</Date>
<Name></Name>
</Fields>
<Fields>
<PositionID>000100</PositionID>
<Date>2021-04-19</Date>
<Name></Name>
</Fields>
</Reports>
</xsl:variable>
<xsl:variable name="ExtractB">
<AOID>
<Employee>
<Name>YYY</Name>
<PositionID>000100</PositionID>
</Employee>
<Employee>
<Name>XXX</Name>
<PositionID>000101</PositionID>
</Employee>
</AOID>
</xsl:variable>
<xsl:template match="/">
<xsl:if test="$ExtractA/Reports[1]/Fields[1]/Name != ''">
<xsl:copy-of select="$ExtractA" />
</xsl:if>
<xsl:if test="$ExtractA/Reports[1]/Fields[1]/Name = ''">
<Reports>
<xsl:for-each-group select="$ExtractA/Reports/Fields, $ExtractB/AOID/Employee" group-by="PositionID">
<xsl:copy>
<xsl:copy-of select="current-group()[1]/Date, PositionID, current-group()[2]/Name"/>
</xsl:copy>
</xsl:for-each-group>
</Reports>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
解决方案
您可以在没有说明的情况下做得更好xsl:key
:
<xsl:variable name="ExtractA" select="document('a.xml')" />
<xsl:variable name="ExtractB" select="document('b.xml')" />
<xsl:template match="/">
<Reports>
<xsl:for-each select="$ExtractA/Reports/Fields">
<Fields>
<xsl:variable name="curItemID" select="PositionID" />
<xsl:variable name="secItem" select="$ExtractB/AOID/Employee[PositionID=$curItemID]" />
<xsl:choose>
<xsl:when test="not(normalize-space(Name))">
<xsl:copy-of select="$secItem/Name" />
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="Name" />
</xsl:otherwise>
</xsl:choose>
<xsl:copy-of select="Date" />
<xsl:copy-of select="PositionID" />
</Fields>
</xsl:for-each>
</Reports>
</xsl:template>
该表达式not(normalize-space(Name))
匹配空字符串或不存在的元素。
您的样本的输出是
<Reports>
<Fields>
<Name>XXX</Name>
<Date>2021-04-19</Date>
<PositionID>000101</PositionID>
</Fields>
<Fields>
<Name>YYY</Name>
<Date>2021-04-19</Date>
<PositionID>000100</PositionID>
</Fields>
</Reports>
这种方法的缺点是,输出仅包含文件 A 中的项目。如果文件 B 包含更多项目,它们将被忽略。
推荐阅读
- javascript - 谷歌图表文本方向
- javascript - Meteor 弹出语义 UI
- c# - 使用 c# 将 .pst 导入 mysql 时,电子邮件地址无法正确显示
- c# - UseStaticFiles OnPrepareResponse 在运行时切换流
- java - 使用 For 循环手动创建堆栈的困难
- swift - Swift 和多个条件?
- sql - 当我删除一行时,如何自动从连接表中删除另一行?
- oauth-2.0 - 使用 OpenID Connect 和 OAuth 管理应用程序访问
- css - 仅在更大的屏幕上使用 CSS Bootstrap 类(卡片)
- javascript - 如何使用 iOS WKWebView 注入 JavaScript 回调来检测 onclick 事件?