我正在尝试使用Saxon 9.1.0.7进行简单的外部查找,从而留下我的头发。
我有一个简单的源文件 dummy.xml :
<something>
<monkey>
<genrecode>AAA</genrecode>
</monkey>
<monkey>
<genrecode>BBB</genrecode>
</monkey>
<monkey>
<genrecode>ZZZ</genrecode>
</monkey>
<monkey>
<genrecode>ZER</genrecode>
</monkey>
</something>
然后查找文件是 GenreSet_124.xml :
<GetGenreMappingObjectsResponse>
<tuple>
<old>
<GenreMapping DepartmentCode="AAA"
DepartmentName="AND - NEWS AND CURRENT AFFAIRS"
Genre="10 - NEWS"/>
</old>
</tuple>
<tuple>
<old>
<GenreMapping DepartmentCode="BBB"
DepartmentName="AND - NEWS AND CURRENT AFFAIRS"
Genre="11 - NEWS"/>
</old>
</tuple>
... lots more
</GetGenreMappingObjectsResponse>
我想要实现的只是根据“DepartmentCode”值来获取“类型”值。
所以我的XSL看起来像:
...
<!-- Set up the genre lookup key -->
<xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/>
<xsl:variable name="lookupDoc" select="document('GenreSet_124.xml')"/>
<xsl:template match="/something">
<stuff>
<xsl:for-each select="monkey">
<Genre>
<xsl:apply-templates select="$lookupDoc">
<xsl:with-param name="curr-label" select="genrecode"/>
</xsl:apply-templates>
</Genre>
</xsl:for-each>
</stuff>
</xsl:template>
<xsl:template match="GetGenreMappingObjectsResponse">
<xsl:param name="curr-genrecode"/>
<xsl:value-of select="key('genre-lookup', $curr-genrecode)/@Genre"/>
</xsl:template>
...
我遇到的问题是我什么都没收到。我目前刚刚获得
<?xml version="1.0" encoding="UTF-8"?>
<stuff>
<Genre/>
<Genre/>
<Genre/>
<Genre/>
</stuff>
我已将所有查找数据移动为GenreMapping的属性,以前作为GenreMapping的子元素,每当我输入模板match =“GetGenreMappingObjectsResponse”时,它只会打印出每个GenreMapping(DepartmentCode,DepartmentName,Genre)中的所有文本!
我不能为我的生活弄清楚我做错了什么。任何帮助/建议将不胜感激。
请找到当前的实际XSLT列表:
<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- Define the global parameters -->
<xsl:param name="TransformationID"/>
<xsl:param name="TransformationType"/>
<!-- Specify that XML is the desired output type -->
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<!-- Set up the genre matching capability -->
<xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/>
<xsl:variable name="documentPath"><xsl:value-of select="concat('GenreSet_',$TransformationID,'.xml')"/></xsl:variable>
<xsl:variable name="lookupDoc" select="document($documentPath)"/>
<!-- Start the first match on the Root level -->
<xsl:template match="/something">
<stuff>
<xsl:for-each select="monkey">
<Genre>
<xsl:apply-templates select="$lookupDoc/*">
<xsl:with-param name="curr-genrecode" select="string(genrecode)"/>
</xsl:apply-templates>
</Genre>
</xsl:for-each>
</stuff>
</xsl:template >
<xsl:template match="GetGenreMappingObjectsResponse">
<xsl:param name="curr-genrecode"/>
<xsl:value-of select="key('genre-lookup', $curr-genrecode, $lookupDoc)/@Genre"/>
</xsl:template>
</xsl:stylesheet>
TransformationID始终是124(因此打开了正确的查找文件。类型只是我目前没有使用但打算使用的名称。
答案 0 :(得分:8)
在XSLT 2.0中,有两种方法可以做到你想要的:
一个是key
函数的三参数版本。第三个参数允许您指定希望密钥处理的根节点(默认情况下,它始终是主文档的根目录):
<xsl:value-of select="key('genre-lookup', $curr-genrecode,$lookupDoc)/@Genre"/>
另一种方法是使用key
节点下的$lookupDoc
函数:
<xsl:value-of select="$lookupDoc/key('genre-lookup', $curr-genrecode)/@Genre"/>
这两种方法都记录在XSLT 2.0 specification on keys中,并且在XSLT 1.0中不起作用。
为了完整起见,如果您仅限于XSLT 1.0,则必须将其重写为不使用密钥。
<xsl:value-of select="$lookupDoc//GenreMapping[@DepartmentCode = $curr-genrecode]/@Genre"/>
啊哈!问题是select="$lookupDoc"
调用中的apply-templates
正在调用默认模板而不是您期望的模板,因此参数会丢失。
将其更改为:
<xsl:apply-templates select="$lookupDoc/*">
<xsl:with-param name="curr-genrecode" select="string(genrecode)"/>
</xsl:apply-templates>
这将正确调用您的模板,密钥应该可以正常工作。
所以最终的XSLT表看起来应该是这样的:
<xsl:variable name="lookupDoc" select="document('XMLFile2.xml')"/>
<xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/>
<xsl:template match="/something">
<stuff>
<xsl:for-each select="monkey">
<Genre>
<xsl:apply-templates select="$lookupDoc/*">
<xsl:with-param name="curr-genrecode" select="string(genrecode)"/>
</xsl:apply-templates>
</Genre>
</xsl:for-each>
</stuff>
</xsl:template>
<xsl:template match="GetGenreMappingObjectsResponse">
<xsl:param name="curr-genrecode"/>
<xsl:value-of select="key('genre-lookup',$curr-genrecode,$lookupDoc)/@Genre"/>
</xsl:template>
答案 1 :(得分:0)
好的,所以这有点精神上,我并没有声称理解它,但它有效(听起来像是软件职业)。
我遇到的问题是,当我调用apply-templates并将外部文档作为变量传递时,它甚至不会匹配任何名为“Genremapping”的模板。
所以我用一个通配符来捕获它,同样在调用apply-templates时我将节点集缩小为我感兴趣的孩子。这是非常疯狂的我可以打印出节点的名称并看到“GenreMapping”但它从未进入任何我称之为“GenreMapping”的模板,而只选择转到“*”模板。
这意味着每个GenreMapping节点都会调用我的新模板匹配,因此可能效率不高。我所意识到的是,如果谓词匹配,我需要做的就是打印出来。
所以它现在看起来像这样(没有使用任何密钥):
...
<xsl:template match="/something">
<stuff>
<xsl:for-each select="monkey">
<Genre>
<key_value><xsl:value-of select="genrecode"/></key_value>
<xsl:variable name="key_val"><xsl:value-of select="genrecode"/></xsl:variable>
<code>
<xsl:apply-templates select="$lookupDoc/*/*/*/*">
<xsl:with-param name="curr-genrecode" select="string(genrecode)"/>
</xsl:apply-templates>
</code>
</Genre>
</xsl:for-each>
</stuff>
</xsl:template >
<xsl:template match="*">
<xsl:param name="curr-genrecode"/>
<xsl:value-of select=".[@DepartmentCode = $curr-genrecode]/@Genre"/>
</xsl:template>
...
所有输出: 注意,最后一个key_value没有正确的代码条目,因为查找文档中没有匹配项。
<?xml version="1.0" encoding="UTF-8"?>
<stuff xmlns:xs="http://www.w3.org/2001/XMLSchema">
<Genre>
<key_value>AAA</key_value>
<code>10 - NEWS</code>
</Genre>
<Genre>
<key_value>AAA</key_value>
<code>10 - NEWS</code>
</Genre>
<Genre>
<key_value>BBB</key_value>
<code>11 - NEWS</code>
</Genre>
<Genre>
<key_value>SVVS</key_value>
<code/>
</Genre>
</stuff>
回复邮政编码。感谢Welbog的帮助。