6

我正在拔掉我剩下的头发,试图使用 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”值掌握“Genre”值。

所以我的 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(因此打开了正确的查找文件。类型只是我目前未使用但打算使用的名称。

4

2 回答 2

9

在 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"/>

这两种方法都记录在关于 keys 的 XSLT 2.0 规范中,并且在 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>
于 2009-08-14T13:50:50.753 回答
0

好的,所以这有点精神,我不声称理解它,但它有效(听起来像是软件职业)。

我遇到的问题是,当我调用应用模板并将外部文档作为变量传递时,它从未匹配任何模板,即使是称为“类型映射”的模板。

所以我使用通配符来捕捉它,在调用应用模板时,我将节点集缩小为我感兴趣的子节点。这太疯狂了,我可以打印出节点的名称并查看“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>

在邮政编码上回答。感谢您的帮助。

于 2009-08-14T17:04:06.260 回答