首页 > 解决方案 > 如何为索引提取关系 XML 的所有变体

问题描述

我用地方建立了一个索引。输出应该是从大到小,即

纽约、曼哈顿、华尔街

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

所以每当我得到一个 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)

标签: xsltindexing

解决方案


我可能误解了逻辑,但考虑使用键来查找位置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>

推荐阅读