2012-01-20 17 views
3

に一致するすべてのノードを与えるものではありませんは、次のXMLを考える

 XPathDocument doc = new XPathDocument("input.xml"); 
     var nav = doc.CreateNavigator(); 

     var item = nav.Select("//StepFusionSet[@name]"); 
     while (item.MoveNext()) 
     { 
      Debug.WriteLine(item.Current.GetAttribute("name", item.Current.NamespaceURI)); 
     } 

は私に出力を与える:

SF1 
SF2 
SF10 

しかし、次のXSLTファイル:

<?xml version="1.0" ?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="//StepFusionSet"> 
    <xsl:call-template name="a"/> 
    </xsl:template> 

    <xsl:template name="a"> 
     <xsl:apply-templates select="@name"/> 
    </xsl:template> 
</xsl:stylesheet> 

(C#のコードによって呼び出さ:)

 XslTransform xslt = new XslTransform(); 
     xslt.Load("transform.xslt"); 
     XPathDocument doc = new XPathDocument("input.xml"); 
     MemoryStream ms = new MemoryStream(); 

     xslt.Transform(doc, null, ms); 

は私に出力を与える:

SF1 
SF10 

私は私のXSLTファイルに間違って何をやっていますか?

答えて

4

あなたSF1と(ネスト)SF2の要素に適用されるように... ...

<xsl:template match="//StepFusionSet"> 

をあなたの最初のテンプレートを考えてみましょう:テンプレートは、あなたの外側SF1要素にマッチする

<StepFusionSet name="SF1"> 
    <StepFusionSet name="SF2"> 
    </StepFusionSet> 
</StepFusionSet> 

。ただし、一致する要素の子に再度適用する必要があります。SF2に一致するようにします。

これは、2番目のテンプレート定義内で再帰的<xsl:apply-templates/>を埋め込むことによって達成することができます。また

<?xml version="1.0" ?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="//StepFusionSet"> 
    <xsl:call-template name="a"/> 
    </xsl:template> 

    <xsl:template name="a"> 
    <xsl:apply-templates select="@name"/> 
    <xsl:apply-templates/> 
    </xsl:template> 

</xsl:stylesheet> 

、あなたは、(SF2など、ネストされたものを含む)すべての<StepFusionSet>要素を選択する<xsl:for-each>要素を使用することができます。

<?xml version="1.0" ?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/"> 
    <xsl:for-each select="//StepFusionSet"> 
     <xsl:value-of select="@name"/> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 
1

あなたの間違いは、match = "// StepFusion"のテンプレートがすべてのStepFusion要素と一致するため、evを処理するために呼び出されるということですery StepFusion要素です。実際、xsl:apply-templates命令で処理するために選択されたStepFusion要素のみを処理します。

私は、この種の混乱は、より単純で明確なmatch = "StepFusion"ではなく、 "// StepFusion"とのマッチを使用する場所でよく起こると考えています。 match属性は、指定された要素がこのテンプレートルールによる処理に適格かどうかをテストします。このテストに提出する要素を決定するapply-templates命令です。

関連する問題