将来自两个 XML 个文件的信息与一个 XSL 合并
Combine information from two XML files with one XSL
我有两个 XML 文件,其中包含不同的信息:
example.xml
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
<root>
<Module Name="Module A">
<Message>1</Message>
<Message>3</Message>
</Module>
<Module Name="Module B">
<Message>1</Message>
<Message>2</Message>
<Message>4</Message>
</Module>
</root>
和
messages.xml
<?xml version="1.0" encoding="utf-8"?>
<messages>
<message number="1">
<description en="Message One" de="Meldung Eins" />
</message>
<message number="2">
<description en="Error" de="Fehler" />
</message>
<message number="3">
<description en="Warning" de="Warnung" />
</message>
<message number="4">
<description en="Message XY" de="Meldung XY" />
</message>
</messages>
现在我已经创建了一个 XSL 文件来组合信息
stylesheet.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Messages</h2>
<table border="1">
<tr bgcolor="#d3d3d3">
<th>Module Name</th>
<th>Message</th>
<th>Description EN</th>
<th>Description DE</th>
</tr>
<xsl:for-each select="//Message">
<tr>
<xsl:variable name="num">
<xsl:value-of select="."/>
</xsl:variable>
<td>
<xsl:value-of select="../@Name"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
<xsl:for-each select="document('messages.xml')//message">
<xsl:choose>
<xsl:when test="$num = @number">
<td>
<xsl:value-of select="description/@en"/>
</td>
<td>
<xsl:value-of select="description/@de"/>
</td>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
并得到这样的输出
Module Name
Message
Description EN
Description DE
Module A
1
Message One
Meldung Eins
Module A
3
Warning
Warnung
Module B
1
Message One
Meldung Eins
Module B
2
Error
Fehler
Module B
4
Message XY
Meldung XY
有没有比在彼此内部使用两个 for-each 更简单的方法来解决这个问题?
我正在使用 XSLT 1.0
如果只使用这两个值,则不需要 for-each。为文档定义一个变量,一个在 for-each 中,并通过 XPath 访问错误消息文本(如评论中已经提到的):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="docMsg" select="document('messages.xml')//message" />
...
<xsl:for-each select="//Message">
<tr>
<xsl:variable name="num" select="." />
<td>
<xsl:value-of select="../@Name"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
<td>
<xsl:value-of select="$docMsg[@number=$num]/description/@en"/>
</td>
<td>
<xsl:value-of select="$docMsg[@number=$num]/description/@de"/>
</td>
</tr>
</xsl:for-each>
但是如果你想遍历所有的属性,你可以使用 for-each:
<xsl:for-each select="//Message">
<tr>
<xsl:variable name="num" select="." />
<td>
<xsl:value-of select="../@Name"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
<xsl:for-each select="$docMsg[@number=$num]/description/@*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
这会遍历 <description>
的所有属性(每个属性一列)。但要注意属性在元素中的顺序必须始终相同。如果不是,您可以在内部 for-each 中使用 <xsl:sort select="local-name()" />
对它们进行排序。
我有两个 XML 文件,其中包含不同的信息:
example.xml
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
<root>
<Module Name="Module A">
<Message>1</Message>
<Message>3</Message>
</Module>
<Module Name="Module B">
<Message>1</Message>
<Message>2</Message>
<Message>4</Message>
</Module>
</root>
和
messages.xml
<?xml version="1.0" encoding="utf-8"?>
<messages>
<message number="1">
<description en="Message One" de="Meldung Eins" />
</message>
<message number="2">
<description en="Error" de="Fehler" />
</message>
<message number="3">
<description en="Warning" de="Warnung" />
</message>
<message number="4">
<description en="Message XY" de="Meldung XY" />
</message>
</messages>
现在我已经创建了一个 XSL 文件来组合信息
stylesheet.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Messages</h2>
<table border="1">
<tr bgcolor="#d3d3d3">
<th>Module Name</th>
<th>Message</th>
<th>Description EN</th>
<th>Description DE</th>
</tr>
<xsl:for-each select="//Message">
<tr>
<xsl:variable name="num">
<xsl:value-of select="."/>
</xsl:variable>
<td>
<xsl:value-of select="../@Name"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
<xsl:for-each select="document('messages.xml')//message">
<xsl:choose>
<xsl:when test="$num = @number">
<td>
<xsl:value-of select="description/@en"/>
</td>
<td>
<xsl:value-of select="description/@de"/>
</td>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
并得到这样的输出
Module Name | Message | Description EN | Description DE |
---|---|---|---|
Module A | 1 | Message One | Meldung Eins |
Module A | 3 | Warning | Warnung |
Module B | 1 | Message One | Meldung Eins |
Module B | 2 | Error | Fehler |
Module B | 4 | Message XY | Meldung XY |
有没有比在彼此内部使用两个 for-each 更简单的方法来解决这个问题?
我正在使用 XSLT 1.0
如果只使用这两个值,则不需要 for-each。为文档定义一个变量,一个在 for-each 中,并通过 XPath 访问错误消息文本(如评论中已经提到的):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="docMsg" select="document('messages.xml')//message" />
...
<xsl:for-each select="//Message">
<tr>
<xsl:variable name="num" select="." />
<td>
<xsl:value-of select="../@Name"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
<td>
<xsl:value-of select="$docMsg[@number=$num]/description/@en"/>
</td>
<td>
<xsl:value-of select="$docMsg[@number=$num]/description/@de"/>
</td>
</tr>
</xsl:for-each>
但是如果你想遍历所有的属性,你可以使用 for-each:
<xsl:for-each select="//Message">
<tr>
<xsl:variable name="num" select="." />
<td>
<xsl:value-of select="../@Name"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
<xsl:for-each select="$docMsg[@number=$num]/description/@*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
这会遍历 <description>
的所有属性(每个属性一列)。但要注意属性在元素中的顺序必须始终相同。如果不是,您可以在内部 for-each 中使用 <xsl:sort select="local-name()" />
对它们进行排序。