2012-03-13 42 views
1

我有一個表模式,它具有一些元字段數據,我需要將其拉低到行級別。使用xsl:key檢索同級:

所以這...

<tables> 
    <table name="T01"> 
     <columns> 
      <column name="F01"> 
       <heading>Field 1</heading> 
      </column > 
      <column name="F02"> 
       <heading>Field 2</heading> 
      </column> 
     </columns> 
     <rows> 
      <row> 
       <field name="F01">AAAAA</field> 
       <field name="F02">BBBBB</field> 
      </row> 
      <row> 
       <field name="F01">DDDDD</field> 
       <field name="F02">EEEEE</field> 
      </row> 
     </rows> 
    </table> 
    <table name="T02"> 
     <!-- ... --> 
    </table> 
</tables> 

應該成爲這個...

<tables> 
    <table name="T01"> 
     <rows> 
      <row> 
       <field name="F01"> 
        <heading>Field 1</heading> 
        <value>AAAAA</value> 
       </field> 
       <field name="F02">      
        <heading>Field 2</heading> 
        <value>BBBBB</value> 
       </field> 
      </row> 
      <row> 
       <field name="F01"> 
        <heading>Field 1</heading> 
        <value>DDDDD</value> 
       </field> 
       <field name="F02">      
        <heading>Field 2</heading> 
        <value>EEEEE</value> 
       </field> 
      </row> 
     </rows> 
    </table> 
    <table name="T02"> 
     <!-- ... --> 
    </table> 
</tables> 

我相信有噸簡單的方式與XSLT要做到這一點,但由於我的工具,我真的需要通過一個鍵()來檢索列標題。因此,像這樣......

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

    <!-- This won't work but if it did ... --> 
    <xsl:key name="field-heading" 
      match="../../columns/column/heading" 
      use="../@name" /> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 


    <xsl:template match="field"> 
    <field name="{@name}"> 
     <heading> 
     <xsl:value-of select="key('field-heading', @name)"/> 
     </heading> 
     <value> 
     <xsl:value-of select="."/> 
     </value> 
    </field> 
    </xsl:template> 

    <xsl:template match="columns"/> 

</xsl:stylesheet> 

但是在xsl:鑰匙匹配屬性不允許父軸,我不知道是否有任何其他方式使其適合。

回答

0

稍微簡單的解決方案

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kColByNames" match="column" use= 
    "concat(../../@name, '+', @name)"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="field"> 
    <xsl:copy> 
    <xsl:copy-of select="@*"/> 
    <heading> 
    <xsl:value-of select= 
     "key('kColByNames', concat(ancestor::table[1]/@name, '+', @name))"/> 
    </heading> 
    <value><xsl:value-of select="."/></value> 
    </xsl:copy> 
</xsl:template> 
<xsl:template match="columns"/> 
</xsl:stylesheet> 

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

<tables> 
    <table name="T01"> 
     <columns> 
      <column name="F01"> 
       <heading>Field 1</heading> 
      </column> 
      <column name="F02"> 
       <heading>Field 2</heading> 
      </column> 
     </columns> 
     <rows> 
      <row> 
       <field name="F01">AAAAA</field> 
       <field name="F02">BBBBB</field> 
      </row> 
      <row> 
       <field name="F01">DDDDD</field> 
       <field name="F02">EEEEE</field> 
      </row> 
     </rows> 
    </table> 
    <table name="T02"> 
     <!-- ... --> 
    </table> 
</tables> 

有用,正確的結果產生

<tables> 
    <table name="T01"> 
     <rows> 
     <row> 
      <field name="F01"> 
       <heading>Field 1</heading> 
       <value>AAAAA</value> 
      </field> 
      <field name="F02"> 
       <heading>Field 2</heading> 
       <value>BBBBB</value> 
      </field> 
     </row> 
     <row> 
      <field name="F01"> 
       <heading>Field 1</heading> 
       <value>DDDDD</value> 
      </field> 
      <field name="F02"> 
       <heading>Field 2</heading> 
       <value>EEEEE</value> 
      </field> 
     </row> 
     </rows> 
    </table> 
    <table name="T02"><!-- ... --></table> 
</tables> 

說明:覆蓋身份規則和使用複合密鑰 - 一個column由其name識別屬性和其祖父母tablename屬性。

0

的主要問題是,關鍵定義的上下文是文檔不是你使用的關鍵,因此定義應該是

<xsl:key name="field-heading" 
    match="/tables/table/columns/column/heading" 
    use="../@name" /> 

有一對夫婦在你的XML錯別字的地方 - 這是我想應該是

<?xml version="1.0" encoding="iso-8859-1"?> 
<?xml-stylesheet type="text/xsl" href="C:/Users/morank/Documents/temp/code.xsl"?> 
<tables> 
    <table name="T01"> 
     <columns> 
      <column name="F01"> 
       <heading>Field 1</heading> 
      </column> 
      <column name="F02"> 
       <heading>Field 2</heading> 
      </column> 
     </columns> 
     <rows> 
      <row> 
       <field name="F01">AAAAA</field> 
       <field name="F02">BBBBB</field> 
      </row> 
      <row> 
       <field name="F01">DDDDD</field> 
       <field name="F02">EEEEE</field> 
      </row> 
     </rows> 
    </table> 
    <table name="T02"> 
     <!-- ... --> 
    </table> 
</tables> 

應用以下XSLT

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

    <!-- This won't work but if it did ... --> 
    <xsl:key name="field-heading" 
     match="/tables/table/columns/column/heading" 
     use="../@name" /> 

    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="field"> 
     <field name='{@name}'> 
      <heading> 
       <xsl:value-of select="key('field-heading', @name)"/> 
      </heading> 
      <value> 
       <xsl:value-of select="."/> 
      </value> 
     </field> 
    </xsl:template> 

    <xsl:template match="columns"/> 

</xsl:stylesheet> 

給出所需的輸出:

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="C:/Users/morank/Documents/temp/code.xsl"?><tables> 
    <table name="T01">   
     <rows> 
      <row> 
       <field name="F01"> 
        <heading>Field 1</heading> 
        <value>AAAAA</value> 
       </field> 
       <field name="F02"> 
        <heading>Field 2</heading> 
        <value>BBBBB</value> 
       </field> 
      </row> 
      <row> 
       <field name="F01"> 
        <heading>Field 1</heading> 
        <value>DDDDD</value> 
       </field> 
       <field name="F02"> 
        <heading>Field 2</heading> 
        <value>EEEEE</value> 
       </field> 
      </row> 
     </rows> 
    </table> 
    <table name="T02"> 
     <!-- ... --> 
    </table> 
</tables> 

請注意,我也改變了模板是標準的身份轉換,並確保該字段的名字被複制

+0

查看我對DevNull的評論,並感謝更正。 – 2012-03-13 21:57:44

0

嘗試使用這樣的:

<xsl:key name="field-heading" 
    match="heading" 
    use="parent::column/@name" /> 

在這種情況下,../將不起作用,因爲use路徑不是從根開始的。


編輯

嘗試創建使用table/@namecolumn/@name沿着鑰匙。這應該使它獨一無二。

XML輸入(我希望這代表您的評論的問題。)

<tables> 
    <table name="T01"> 
    <columns> 
     <column name="F01"> 
     <heading>Field 1</heading> 
     </column> 
     <column name="F02"> 
     <heading>Field 2</heading> 
     </column> 
    </columns> 
    <rows> 
     <row> 
     <field name="F01">AAAAA</field> 
     <field name="F02">BBBBB</field> 
     </row> 
     <row> 
     <field name="F01">DDDDD</field> 
     <field name="F02">EEEEE</field> 
     </row> 
    </rows> 
    </table> 
    <table name="T02"> 
    <columns> 
     <column name="F01"> 
     <heading>Field A</heading> 
     </column> 
     <column name="F02"> 
     <heading>Field B</heading> 
     </column> 
    </columns> 
    <rows> 
     <row> 
     <field name="F01">11111</field> 
     <field name="F02">22222</field> 
     </row> 
     <row> 
     <field name="F01">44444</field> 
     <field name="F02">55555</field> 
     </row> 
    </rows> 
    </table> 
</tables> 

修改XSLT 1。0

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

    <!-- This won't work but if it did ... --> 
    <xsl:key name="field-heading" 
    match="heading" 
    use="concat(ancestor::table/@name,'+',parent::column/@name)" /> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="field"> 
    <field name="{@name}"> 
     <heading> 
     <xsl:value-of select="key('field-heading', concat(ancestor::table/@name,'+',@name))"/> 
     </heading> 
     <value> 
     <xsl:value-of select="."/> 
     </value> 
    </field> 
    </xsl:template> 

    <xsl:template match="columns"/> 

</xsl:stylesheet> 

XML輸出

<tables> 
    <table name="T01"> 

     <rows> 
     <row> 
      <field name="F01"> 
       <heading>Field 1</heading> 
       <value>AAAAA</value> 
      </field> 
      <field name="F02"> 
       <heading>Field 2</heading> 
       <value>BBBBB</value> 
      </field> 
     </row> 
     <row> 
      <field name="F01"> 
       <heading>Field 1</heading> 
       <value>DDDDD</value> 
      </field> 
      <field name="F02"> 
       <heading>Field 2</heading> 
       <value>EEEEE</value> 
      </field> 
     </row> 
     </rows> 
    </table> 
    <table name="T02"> 

     <rows> 
     <row> 
      <field name="F01"> 
       <heading>Field A</heading> 
       <value>11111</value> 
      </field> 
      <field name="F02"> 
       <heading>Field B</heading> 
       <value>22222</value> 
      </field> 
     </row> 
     <row> 
      <field name="F01"> 
       <heading>Field A</heading> 
       <value>44444</value> 
      </field> 
      <field name="F02"> 
       <heading>Field B</heading> 
       <value>55555</value> 
      </field> 
     </row> 
     </rows> 
    </table> 
</tables> 
+0

只有當列/字段名稱在所有表中唯一或至少共享相同的標題文本時,這纔會起作用。我正朝着保險/假設後面走。但不是我期望的 – 2012-03-13 21:56:53

+0

@ryse - 我希望我能正確理解這個問題。請看看我的編輯,並讓我知道如果這就是你要找的。 – 2012-03-13 22:16:05

+0

我認爲這是我能得到的最接近的。我真的希望這不會改變'use'除了列/字段名稱以外的其他任何東西,但是希望的方形插件似乎不適合XSLT的圓孔。 – 2012-03-14 15:38:37