我一直在尝试使用基于XML文件中相同属性值的XSLT创建表。我正在努力将基于相同属性的元素链接起来,并循环检索必要数据的XML文件。
我有的XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<LandXML>
<Survey>
<GPSSetup id="Setup1" stationName="Ref1">
</GPSSetup>
<GPSSetup id="Setup2" stationName="Ref2">
</GPSSetup>
<GPSSetup id="Setup3" stationName="Ref3">
</GPSSetup>
...
</Survey>
<Survey>
<GPSSetup id="id1" name="0001">
</GPSSetup>
<GPSSetup id="id2" name="0002">
</GPSSetup>
<GPSSetup id="id3" name="0003">
</GPSSetup>
...
<GPSVector setupID_a="Ref1">
<TargetPoint pntRef="0001"></TargetPoint>
</GPSVector>
<GPSVector setupID_a="Ref1">
<TargetPoint pntRef="0002"></TargetPoint>
</GPSVector>
<GPSVector setupID_a="Ref2">
<TargetPoint pntRef="0003"></TargetPoint>
</GPSVector>
...
</Survey>
<HexagonLandXML>
<Point uniqueID="0001">
<Coordinates n="1234"></Coordinates>
</Point>
<Point uniqueID="name2">
<Coordinates n="1225"></Coordinates>
</Point>
<Point uniqueID="name3">
<Coordinates n="1335"></Coordinates>
</Point>
</HexagonLandXML>
</LandXML>
我想在每个&#34; stationName&#34;下输出一个html文件。在XML中找到的值,创建一个表,其中对应的&#34; pntRef&#34;和&#34; n&#34;值显示。
我希望实现的输出:
Ref1:
0001 1234
0002 1225
Ref2:
0003 1335
我到目前为止所做的XSLT文件:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:l="http://www.landxml.org/schema/LandXML-1.2"
xmlns:h="http://xml.hexagon.com/schema/HeXML-1.7"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="h l"
extension-element-prefixes="h l msxsl">
<xsl:output method="html" indent="no" encoding="utf-8"/>
<xsl:variable name="fileExt" select="'html'"/>
<xsl:template match="/">
<html>
<head>
<style>
</style>
</head>
<body>
<xsl:apply-templates select="//l:LandXML/l:Survey[1]/l:GPSSetup">
</xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:key name="keyLGPSVector" match="l:GPSVector" use="@setupID_A"/>
<xsl:key name="keyH" match="h:Point" use="@uniqueID"/>
<xsl:template match="//l:LandXML/l:Survey[1]/l:GPSSetup">
<xsl:variable name="Survey1L" select="."/>
<xsl:variable name="Survey1LID" select="key('keyLGPSVector', $Survey1L/@id)"/>
<xsl:variable name="PointH" select="key('keyH', $Survey1L/@id)"/>
<xsl:for-each select=".">
<h5>
<xsl:value-of select="@stationName"/>
</h5>
<table>
<thead>
<tr>
<th>Number</th>
<th>n [m]</th>
</tr>
</thead>
<tbody>
<xsl:for-each select="$Survey1LID">
<xsl:if test="$Survey1LID/@setupID_A = $Survey1L/@id">
<tr>
<td><xsl:value-of select="current()/l:TargetPoint/@pntRef"/></td>
<td><xsl:value-of select="$PointH/h:Coordinates/@n"/></td>
</tr>
</xsl:if>
</xsl:for-each>
</tbody>
</table>
</xsl:for-each>
有了这个,我就可以实现正确的&#34; pntRef&#34;值显示在每个&#34; Ref()&#34;标题,但我不能得到&#34; n&#34;值。从阅读这个论坛,我明白for-each可能不是在这种情况下使用的最佳元素。
很抱歉,如果编辑错误或不透明,这是我的第一篇文章。
答案 0 :(得分:1)
您不需要<xsl:for-each select=".">
,您可以将其删除为模板内部,但无论如何只有一个上下文节点。
然后我认为您应该将<xsl:variable name="PointH" select="key('keyH', $Survey1L/@id)"/>
移到第二个for-each
内,而不是<xsl:variable name="PointH" select="key('keyH', TargetPoint/@pntRef)"/>
。
如果您仍然遇到问题,请考虑将XML和XSLT示例编辑为最小但完整且一致的,目前您的XML示例并未显示任何名称空间,但您的XSLT至少假定为两个。
答案 1 :(得分:1)
我认为这就是你所需要的;请参阅解释说明:XSLT Fiddle
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array"
version="3.0">
<!-- create the html body -->
<xsl:template match="/">
<html>
<head>
<style></style>
</head>
<body>
<xsl:apply-templates select="/LandXML/Survey/GPSSetup[./@stationName]" />
</body>
</html>
</xsl:template>
<!-- create an entry per station -->
<xsl:template match="/LandXML/Survey/GPSSetup">
<xsl:variable name="stationName" select="./@stationName" />
<h5>
<xsl:value-of select="$stationName"/>
</h5>
<table>
<thead>
<tr>
<th>Number</th>
<th>n [m]</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="../../Survey/GPSVector[@setupID_a = $stationName]/TargetPoint" />
</tbody>
</table>
</xsl:template>
<!-- find all target points related to the station -->
<xsl:template match="/LandXML/Survey/GPSVector/TargetPoint">
<xsl:variable name="pntRef" select="./@pntRef" />
<xsl:apply-templates select="../../../HexagonLandXML/Point[@uniqueID = $pntRef]/Coordinates" />
</xsl:template>
<!-- create a row for each target point / coordinate pair under the station -->
<xsl:template match="/LandXML/HexagonLandXML/Point/Coordinates">
<tr>
<td><xsl:value-of select="../@uniqueID" /></td>
<td><xsl:value-of select="./@n" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>
<xsl:template match="/LandXML/HexagonLandXML/Point/Coordinates">
会创建包含uniqueID
和n
值的行;但是不知道应该放在哪里。<xsl:apply-templates select="../../../HexagonLandXML/Point[@uniqueID = $pntRef]/Coordinates" />
从上面的模板中撤回这些结果,其中uniqueID
值与当前模板的pntRef
值匹配;所以我们只显示每个pntRef的相关行。注意:我在我的选择中使用了相对XPath(../../../HexagonLandXML/Point[@uniqueID = $pntRef]/Coordinates
;但同样可以使用绝对值(/LandXML/HexagonLandXML/Point[@uniqueID = $pntRef]/Coordinates
)。相对的一个在当前模板的匹配上下文中起作用,而绝对一个起作用来自源文档的根元素。后者可能更容易理解;但如果从XML的结构中推断出任何关系,前者可能会有用(尽管我认为这不是这种情况)。apply-templates
过滤另一个模板匹配的技巧。