如何为索引提取关系XML的所有变体

时间:2018-11-15 11:16:36

标签: xslt indexing

我建立了带有地点的索引。输出应该从大到小,即

  

纽约,曼哈顿,华尔街

问题是,有时候街道不属于一个地区,而是属于两个地区,有时甚至根本没有地区,但街道被直接列在城市下。

因此,每当我获得idno并在这样的代码上使用它时:

<?xml version="1.0" encoding="UTF-8"?>
<listplaces>
    <place>
       <placeName type="city">City A</placeName>
        <idno>CA</idno>
    </place>
    <place>
        <placeName type="district">District B</placeName>
        <idno>DB</idno>
        <belongsTo active="CA" passive="DB"/>
    </place>
    <place>
        <placeName type="district">District C</placeName>
        <idno>DC</idno>
        <belongsTo active="CA" passive="DC"/>
    </place>
    <place>
        <placeName type="street">Street D</placeName>
        <idno>SD</idno>
        <belongsTo active="DB" passive="SD"/>
        <belongsTo active="DC" passive="SD"/>
    </place>
    <place>
        <placeName type="street">Street E</placeName>
        <idno>SE</idno>
        <belongsTo active="CA" passive="SE"/>
    </place>
</listplaces>

这应该根据idno输出

idno CA: City A
idno DB: City A, District B
idno DC: City A, District C
idno SD: City A, District B, Street D
idno SD: City A, District C, Street D
idno SE: City A, Street E

问题是,当我处于最低级别时,以正确的顺序创建输出-跟随所有@active关系到顶部。我找到了一个解决方案,在该解决方案中,我始终在字符串的左侧连接活动的placeName。但是我不知道如何让XSLT处理所有可能的变体并相应地创建所需的字符串。

(我使用XSLT 3.0)

2 个答案:

答案 0 :(得分:1)

我可能对逻辑有误解,但考虑使用按键通过belongTo

查找位置
<xsl:key name="places" match="place" use="belongsTo/@active" />

您将从选择第一位开始($idno是包含所需值的参数)

<xsl:apply-templates select="place[idno = $idno]" />

然后在与place匹配的模板中进行输出,您将像这样处理其“子级”

<xsl:apply-templates select="key('places', idno)">

这还将把“路径”的参数传递到当前位置。

尝试使用此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" expand-text="yes">
  <xsl:output method="text"/>

  <xsl:key name="places" match="place" use="belongsTo/@active" />

  <xsl:param name="idno" select="'CA'" />

  <xsl:template match="/*">
    <xsl:apply-templates select="place[idno = $idno]" />
  </xsl:template>

  <xsl:template match="place">
    <xsl:param name="previous" />
    <xsl:variable name="new" select="$previous[normalize-space()], placeName" />
    <xsl:text>idno {idno}: </xsl:text>
    <xsl:value-of select="$new" separator=", " />
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates select="key('places', idno)">
      <xsl:with-param name="previous" select="$new" />
    </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

这是使用 XSLT 1.0 的解决方案:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>

<xsl:key name="parent" match="place" use="idno" />

<xsl:template match="place">
    <xsl:choose>
        <xsl:when test="not(belongsTo)">
            <xsl:text>idno </xsl:text>
            <xsl:value-of select="idno" />
            <xsl:text>: </xsl:text>
            <xsl:value-of select="placeName" />
            <xsl:text>&#10;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:apply-templates select="belongsTo"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="belongsTo">
    <xsl:text>idno </xsl:text>
    <xsl:value-of select="../idno" />
    <xsl:text>: </xsl:text>
    <xsl:apply-templates select="key('parent', @active)" mode="path"/>
    <xsl:value-of select="../placeName" />
    <xsl:text>&#10;</xsl:text>
</xsl:template>

<xsl:template match="place" mode="path">
    <xsl:apply-templates select="key('parent', belongsTo/@active)" mode="path"/>
    <xsl:value-of select="placeName" />
    <xsl:text>, </xsl:text>
</xsl:template>

</xsl:stylesheet>

结果

idno CA: City A
idno DB: City A, District B
idno DC: City A, District C
idno SD: City A, District B, Street D
idno SD: City A, District C, Street D
idno SE: City A, Street E

演示http://xsltransform.hikmatu.com/eiZQaEN/1