2015-05-23 70 views
3

嘗試進行此轉換,但無法在Web或文檔中找到答案(newbe here)。在同一輸出行中按屬性的XSLT相關標記

只是試圖讓這樣的事情:

<Info> 
     <Type p="1">MyType1</Type> 
     <Type p="2">MyType2</Type> 
     <Type p="3">MyType3</Type> 
     <Values> 
      <r p="1">MyValue1</r> 
      <r p="2">MyValue2</r> 
      <r p="3">MyValue3</r> 
     </Values> 
</Info> 

顯示爲純文本的轉換是這樣的:

MyType1;MyValue1 
MyType2;MyValue3 
MyType3;MyValue3 

由「P」屬性加入輸出的兩個領域¿可能嗎?

+0

它是一個分組的問題,請說出您是否可以使用XSLT 2.0,或是否需要一個XSLT 1.0解決方案。 –

+0

@Esecede - 我假設上面的輸出在第2行有一個錯字 - 它應該讀取MyType2; MyValue2而不是MyType2; MyValue3 – JohnRC

+0

@JohnRC,的確,有一個錯字,謝謝指出。 – Esecede

回答

1

這是一個相當簡單的方法

<xsl:template match="/"> 

    <xsl:variable name="newline"> 
    <xsl:text>&#xa;</xsl:text> 
    </xsl:variable> 

    <xsl:for-each select="/Info/Type" > 
    <xsl:variable name="p" select="@p" /> 
    <xsl:value-of select="." /> 
    <xsl:text>;</xsl:text> 
    <xsl:value-of select=" /Info/Values/r[@p=$p] " /> 
    <xsl:if test=" position() != last() "> 
     <xsl:value-of select="$newline" /> 
    </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

這樣只會選取第一匹配每個t的值/ r節點他鍵入節點。因此,假定任何具有相同@p的更多值/ r節點都應該被忽略。

+0

這就像一個魅力,謝謝 – Esecede

1

一種可能的解決方案是使用一個模板匹配Type打印隨後根據r元素的值和一個空的模板匹配Values避免打印ValuesType值的兩倍這樣的:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 
<xsl:strip-space elements="*"/> 
<xsl:template match="Type"> 
<xsl:variable name="current" select="@p"/> 
    <xsl:value-of select="."/> 
    <xsl:value-of select="concat(';',//Values/r[@p=$current])"/> 
    <xsl:if test="position() != last()"> 
    <xsl:text>&#xa;</xsl:text> 
    </xsl:if> 
</xsl:template> 
<xsl:template match="Values"/> 
</xsl:transform> 

應用到您輸入如下輸出產生:

MyType1;MyValue1 
MyType2;MyValue2 
MyType3;MyValue3 
4

XSLT具有a built-in mechanism for handling cross-references;這將是最好的使用方法:

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:key name="value" match="r" use="@p" /> 

<xsl:template match="/Info"> 
    <xsl:for-each select="Type"> 
     <xsl:value-of select="."/> 
      <xsl:text>;</xsl:text> 
      <xsl:for-each select="key('value', @p)"> 
       <xsl:value-of select="."/> 
       <xsl:if test="position()!= last()"> 
        <xsl:text>;</xsl:text> 
       </xsl:if> 
      </xsl:for-each>  
     <xsl:if test="position()!= last()"> 
      <xsl:text>&#10;</xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 

假設:

  1. 每個Type項是唯一的;
  2. 可能有多個相同類型的值;例如,下面的輸入:

    <Info> 
    <Type p="1">MyType1</Type> 
    <Type p="2">MyType2</Type> 
    <Type p="3">MyType3</Type> 
    <Values> 
        <r p="1">MyValue1</r> 
        <r p="2">MyValue2a</r> 
        <r p="2">MyValue2b</r> 
        <r p="3">MyValue3</r> 
    </Values> 
    

    將返回:

    MyType1;MyValue1 
    MyType2;MyValue2a;MyValue2b 
    MyType3;MyValue3 
    
1

使用這個簡單和短的XSLT 1。0溶液

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 
<xsl:strip-space elements="*"/> 
<xsl:key name="kRByP" match="r" use="@p"/> 

<xsl:template match="Type/text()"> 
    <xsl:value-of select="concat(.,';',key('kRByP', ../@p), '&#xA;')"/> 
</xsl:template> 
<xsl:template match="text()"/> 
</xsl:stylesheet> 

當這個變換所提供的源XML文檔施加:

<Info> 
    <Type p="1">MyType1</Type> 
    <Type p="2">MyType2</Type> 
    <Type p="3">MyType3</Type> 
    <Values> 
     <r p="1">MyValue1</r> 
     <r p="2">MyValue2</r> 
     <r p="3">MyValue3</r> 
    </Values> 
</Info> 

有用,正確的結果產生

MyType1;MyValue1 
MyType2;MyValue2 
MyType3;MyValue3 

解釋

  1. 使用鍵,模板匹配和XSLT處理模型的工作方式。只有想要的文本節點被匹配,其餘的被忽略(「刪除」)。
  2. 假設是一個p屬性的值唯一地標識rType元件中,向其中該屬性所屬