2009-09-30 56 views
3

我有下面的代碼塊獲取節點的名稱下的樹,像這樣:獲取XSLT當前節點,格式爲XPath查詢?

section/page/subPage

但是我想能夠得到它歸結爲以下(只是使它達):

section[@id='someId']/page/subPage[@user='UserA']/@title

我發現下面的代碼從這些StackOverflow的職位之一:


<xsl:attribute name="path"> <xsl:for-each select="ancestor-or-self::*"> <xsl:if test="name() != 'root'"> <xsl:value-of select="name()"> <xsl:if test="not(position()=last())"> <xsl:text>/</xsl:text> </xsl:if> </xsl:value-of> </xsl:if> </xsl:for-each> </xsl:attribute> 

這給了我直線路徑,但我想運行更多的邏輯來使它包含@id(或相關屬性),也許還有一些我現在無法想到的東西。

這樣做的最好方法是什麼?

我檢查了EXSLT函數,這可能工作,但也許你們已經解決了這個問題更好的方法。

任何想法?

我使用Ruby的引入nokogiri解析XML/XSLT是否有幫助。

非常感謝, 蘭斯

回答

4

該解決方案你想要做什麼:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" /> 

    <xsl:template match="/"> 
    <root> 
     <xsl:attribute name="path"> 
     <xsl:apply-templates select="(//@title)[1]" mode="make-path" /> 
     </xsl:attribute> 
    </root> 
    </xsl:template> 

    <xsl:template match="*|@*" mode="make-path"> 
    <xsl:apply-templates select="parent::*" mode="make-path" /> 
    <xsl:text>/</xsl:text> 
    <xsl:apply-templates select="." mode="make-name" /> 
    <xsl:choose> 
     <xsl:when test="self::section"> 
     <xsl:apply-templates select="@id" mode="make-predicate" /> 
     </xsl:when> 
     <xsl:when test="self::subPage"> 
     <xsl:apply-templates select="@user" mode="make-predicate" /> 
     </xsl:when> 
    </xsl:choose> 
    </xsl:template> 

    <xsl:template match="*|@*" mode="make-predicate"> 
    <xsl:text>[</xsl:text> 
    <xsl:apply-templates select="." mode="make-name" /> 
    <xsl:text> = '</xsl:text> 
    <xsl:value-of select="." /> 
    <xsl:text>']</xsl:text> 
    </xsl:template> 

    <xsl:template match="*" mode="make-name"> 
    <xsl:value-of select="name()" /> 
    </xsl:template> 

    <xsl:template match="@*" mode="make-name"> 
    <xsl:text>@</xsl:text> 
    <xsl:value-of select="name()" /> 
    </xsl:template> 

</xsl:stylesheet> 

當應用於

<section id="someId"> 
    <page> 
    <subPage user="UserA" title="test" /> 
    <subPage user="UserB" title="blah" /> 
    </page> 
    <page> 
    <subPage user="UserC" title="fooh" /> 
    </page> 
</section> 

你:

<root path="/section[@id = 'someId']/page/subPage[@user = 'UserA']/@title" /> 

<xsl:choose>是配置點(添加儘可能多的<xsl:when> S作爲您喜歡):

<!-- test for element name --> 
<xsl:when test="self::section"> 
    <!-- make predicates out of selected attributes --> 
    <xsl:apply-templates select="@id" mode="make-predicate" /> 
</xsl:when> 

也可以:

<xsl:when test="self::section"> 
    <xsl:apply-templates select="@name|@category|subElement" mode="make-predicate" /> 
</xsl:when> 

,這將導致

<root path="/section[@name = 'someName'][@category = 'somecat'][subElement = 'xyz']/..." /> 

我看到的唯一問題是與包含單引號謂詞值。他們會打破XPath。

+0

很好用的模式 – 2009-09-30 16:47:11

+0

鐵桿男,謝謝你。 – 2009-10-01 00:26:09

1

對於每個祖先節點,你可以遍歷用簡單的XSL所有屬性:對,每個

<xsl:for-each select="@*"> 

然後,您可以使用的屬性建立起來的XPath字符串

<xsl:for-each select="ancestor-or-self::*"> 
    <xsl:if test="name() != 'root'"> 
     <xsl:value-of select="name()"/> 
     <xsl:if test="@*"> 
     <xsl:text>[</xsl:text> 
     <xsl:for-each select="@*"> 
      <xsl:text>@</xsl:text> 
      <xsl:value-of select="name()"/> 
      <xsl:text>='</xsl:text> 
      <xsl:value-of select="."/> 
      <xsl:text>'</xsl:text> 
      <xsl:if test="not(position()=last())"> 
       <xsl:text> and </xsl:text> 
      </xsl:if> 
     </xsl:for-each> 
     <xsl:text>]</xsl:text> 
     </xsl:if> 
     <xsl:if test="not(position()=last())"> 
     <xsl:text>/</xsl:text> 
     </xsl:if> 
    </xsl:if> 
</xsl:for-each>