我试图在xml中使用查找表进行xsl转换。我熟悉xsl并且不关心查找表的物理加载和查询,而是我在编写具有稀疏填充查找的适当XPath时遇到了麻烦。
如果缺少lookup属性,我将使用一个需要回退到默认值的表。以下xml是此人口的一个示例:
<?xml version="1.0" encoding="UTF-8"?>
<codes>
<code id="12" country="ca" areacode="420" division="45"/>
<code id="13" country="ca" areacode="519" division="45"/>
<code id="14" country="ca" areacode="519" division="40"/>
<code id="15" country="ca" division="46"/>
<code id="16" country="ca"/>
<code id="17" country="au"/>
<code id="18" country="au" division="32"/>
</codes>
在进行查找时,我会输入国家,地区代码和分部以找到合适的ID。
我尝试了几种选择,但没有一种是令人满意的。下面的XPath将返回两个条目(我应该得到15的id):
/codes/code[@country='ca' and (@areacode='222' or empty(@areacode)) and (@division='46' or empty(@division))]/@id
我的xsl支持XPath 2.0。
任何帮助将不胜感激!
答案 0 :(得分:3)
如果我正确理解您的要求,那么@country
始终存在,因此我们可以对该属性进行基于密钥的查找。对于其他两个属性@areacode
和@division
,您需要使用code
,其中两个属性都优先于code
,而code
具有一个匹配属性,优先级高于{{ 1}}没有匹配的属性。
所以我只想创建一个不同优先级的序列,然后找到第一个:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="lkp-url" select="'test2013062402.xml'"/>
<xsl:variable name="lkp-doc" select="doc($lkp-url)"/>
<xsl:key name="by-country"
match="code"
use="@country"/>
<xsl:param name="c" select="'ca'"/>
<xsl:param name="ac" select="'222'"/>
<xsl:param name="d" select="'46'"/>
<xsl:template match="/">
<xsl:value-of select="(key('by-country', $c, $lkp-doc)[@areacode = $ac and @division = $d],
key('by-country', $c, $lkp-doc)[not(@areacode) and @division = $d],
key('by-country', $c, $lkp-doc)[@areacode = $ac and not(@division)],
key('by-country', $c, $lkp-doc)[not(@areacode) and not(@division)])[1]/@id"/>
</xsl:template>
</xsl:stylesheet>
我不知道这两个属性中哪一个具有优先级,如果areacode
具有优先权,您可能想要在代码中创建的序列中对第二和第三项进行随机播放。
上述代码应缩短为
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="lkp-url" select="'test2013062402.xml'"/>
<xsl:variable name="lkp-doc" select="doc($lkp-url)"/>
<xsl:key name="by-country"
match="code"
use="@country"/>
<xsl:param name="c" select="'ca'"/>
<xsl:param name="ac" select="'222'"/>
<xsl:param name="d" select="'46'"/>
<xsl:template match="/">
<xsl:variable name="cs" select="key('by-country', $c, $lkp-doc)"/>
<xsl:value-of select="($cs[@areacode = $ac and @division = $d],
$cs[not(@areacode) and @division = $d],
$cs[@areacode = $ac and not(@division)],
$cs[not(@areacode) and not(@division)])[1]/@id"/>
</xsl:template>
</xsl:stylesheet>