2009-07-23 3 views
3

Я читал по разному вопросу о выборе уникальных узлов в документе (используя метод Muenchian), но в моем случае я не могу использовать ключи (или я не знаю как), потому что я работаю над набором узлов, а не с документом.XSL: как выбрать уникальные узлы в узле

И клавиши не могут быть установлены на узле. В принципе у меня есть переменный:

<xsl:variable name="limitedSet" select=" 
    $deviceInstanceNodeSet[position() &lt;= $tableMaxCol]" 
/> 

который содержит <deviceInstance> узлов, которые сами по себе содержащим <structure> элементов набор узлов может быть представлен следующим образом:

<deviceInstance name="Demux TSchannel" deviceIndex="0"> 
    <structure name="DemuxTschannelCaps"> 
    </structure> 
</deviceInstance> 
<deviceInstance name="Demux TSchannel" deviceIndex="1"> 
    <structure name="DemuxTschannelCaps"> 
    </structure> 
</deviceInstance> 
<deviceInstance name="Demux TSchannel" deviceIndex="3"> 
    <structure name="otherCaps"> 
    </structure> 
</deviceInstance> 

И я не знаю, чтобы выбрать <structure> элементов, имеют только другое имя. Выбрать бы в этом примере вернуть два <structure> элементов, являются:

<structure name="DemuxTschannelCaps"></structure> 
<structure name="otherCaps"></structure> 

Я попытался

select="$limitedSet//structure[not(@name=preceding::structure/@name)]" 

но предшествующая ось проходит вдоль всего документа, а не на $limitedSet?

Я застрял, может кто-то мне помочь. Спасибо.

ответ

3
<xsl:variable name="structure" select="$limitedSet//structure" /> 

<xsl:for-each select="$structure"> 
    <xsl:variable name="name" select="@name" /> 
    <xsl:if test="generate-id() = generate-id($structure[@name = $name][1])"> 
    <xsl:copy-of select="." /> 
    </xsl:if> 
</xsl:for-each> 

Это может быть оказана помощь по ключу:

<xsl:key name="kStructureByName" match="structure" use="@name" /> 
<!-- ... --> 
<xsl:if test="generate-id() = generate-id(key('kStructureByName', $name)[1])"> 

В зависимости от вашего входа, ключ должен захватить некоторую дополнительную контекстную информацию:

<xsl:key name="kStructureByName" match="structure" use=" 
    concat(ancestor::device[1]/@id, ',', @name) 
" /> 
<!-- ... --> 
<xsl:variable name="name" select="concat(ancestor::device[1]/@id, ',', @name)" /> 
<xsl:if test="generate-id() = generate-id(key('kStructureByName', $name)[1])"> 
+0

Это является отличный ответ, который сэкономит мой день, большое спасибо за этот быстрый ответ. Этот сайт замечательный, и я зарегистрируюсь, чтобы дать оценку этому ответу. Tahnk вы так много. SeB. – SeB

+0

Я подумал о вашем ключевом предложении, но это не сработает, потому что мне нужна одна структура из нескольких устройств, и ваше предложение работает только для одного устройства. – SeB

+0

@SeB: Не уверен, что вы имеете в виду - мое предложение (по крайней мере, вторая версия ключа) будет работать на нескольких устройствах. Конечно, вам придется адаптировать выражение «use» к вашему фактическому XML, но это не должно быть невозможно. – Tomalak

1
select="$limitedSet//structure[not(@name=preceding::structure[count($limitedSet) = count($limitedSet | ..)]/@name)]" 
+0

Я думаю, что нет, как я уже сказал, axi applis на всем документе, а не на узле. Более того, к моему пониманию предыдущий брат не подходит к другому устройству. Единственное, из чего состоит структура. Но спасибо в любом случае за попытку. – SeB

+0

«предшествующие» и «следующие» оси применяются ко всем документам, но слова «previous-sibling» и «next-sibling» применяются только к узлам с одним и тем же родителем. Вы правы, но не учитываете узлы в других элементах deviceInstance. –

+0

Попробуйте обновленную версию. Мне пришлось придумать взломы, чтобы проверить наличие узлов в '$ limitedSet'. –

Смежные вопросы