0

我正在尝试使用 xml 中的查找表进行 xsl 转换。我熟悉 xsl 并且不关心查找表的物理加载和查询,而是在使用稀疏填充的查找来制定适当的 XPath 时遇到了麻烦。

如果缺少查找属性,我将使用一个需要回退到默认值的表。以下 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。

任何帮助将不胜感激!

4

1 回答 1

3

如果我正确理解您的要求,则@country始终存在,因此我们可以对该属性进行基于键的查找。对于其他两个属性@areacode@division您希望使用code两个属性都与优先级匹配的 a code,其中一个匹配属性的优先级高于code没有匹配属性的 a。

所以我会简单地创建一系列不同的优先级并找到第一个:

<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>
于 2013-06-24T16:14:00.893 回答