首页 > 解决方案 > XSL:针对密钥进行测试

问题描述

我在一个文件中有大量姓名(带有传记细节)people.xml。这些人出现在另一个文件中的随机位置 corpus.xml。它们与@xml:id.

因此在people.xml文件中,有类似的条目

<person xml:id="john_foo"/>
<person xml:id="ann_foo"/>
<person xml:id="sally_foo"/>
...

corpus.xml文件中,我们可以在下面找到这些相同的 xml:ids(文档中的任何位置)@nameref

<corpus>
<p>
  <persName nameref="#john_foo" role="a"/>
  <persName nameref="#ann_foo" role="g"/>
  <s>
     <persName nameref="#john_foo" role="g"/>
  </s>
</p>
<p>
  <persName nameref="#sally_foo" role="a"/>
  <d>
     <persName nameref="#sally_foo" role="p"/>
  </d>
</p>
...
<corpus>

我想测试(使用 XSL 3.0,Saxon)每个都people.xml//@xml:id存在,corpus.xml/corpus//persName/@nameref但只有当@role匹配某个值时。在这种情况下,我只想返回一个“肯定的结果”,如果@role="a"

我正在尝试使用密钥来执行此操作,但它没有返回任何内容:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">

<xsl:key name="namerefs" match="corpus" use=".//persName[@role='a']"/>

<xsl:param name="documt" select="doc('corpus.xml')"/>

<xsl:template match="person">
  <!-- test if exists @xml:id + @role="a" -->
  <xsl:if test="key($namerefs, concat('#',@xml:id) ,$documt")>if found, do something here</xsl:if>
</xsl:template>

</xsl:stylesheet>

我想我没有访问密钥中的正确节点?

提前谢谢了。

注意。更新了各种错别字

标签: xmlxsltxslt-3.0

解决方案


This

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:key name="persName" match="persName" use="substring-after(@nameref, '#')" />
  <xsl:param name="corpusDoc" select="document('corpus.xml')"/>

  <xsl:template match="/">
    <xsl:apply-templates select="//person" />
  </xsl:template>

  <xsl:template match="person">
    <xsl:if test="key('persName', @xml:id, $corpusDoc)[@role = 'a']">
      <xsl:copy-of select="." />
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

outputs

<person xml:id="john_foo"/>
<person xml:id="sally_foo"/>

You can move the predicate [@role = 'a'] from the <xsl:if> to the <xsl:key>. That would work, but I don't think it's worth it.


推荐阅读