2017-04-26 89 views
0

我有一個XML文檔,我用XSLT變換1.0複雜的嵌套元素:XSLT 1.0 - 分組具有屬性

<?xml version="1.0" encoding="UTF-8"?> 
<element tag="container"> 
    <data handle="$1"> 
     ... 
    </data> 
    <assignments/> 
    <expression context="$1"> 
     Object_Text 
    </expression> 
    <expression context="$1"> 
     Object_Text 
    </expression> 
    <expression context="$1"> 
     Object_Heading 
    </expression> 
    <element tag="container"> 
     <data handle="$2"> 
      ... 
     </data> 
     <assignments/> 
     <element tag="container"> 
      <data handle="$3"> 
       ... 
      </data> 
      <assignments/> 
      <expression context="$3"> 
       Object_Text 
      </expression> 
     </element> 
     <element tag="container"> 
      ... 
     </element> 
    </element> 
    <element tag="container"> 
     <element tag="container"> 
      <element tag="container"> 
       <expression context="$1"> 
        Object_Text 
       </expression> 
      </element> 
     </element> 
    </element> 
    <element tag="container"> 
    <expression context="$1"> 
     Object_Identifier 
    </expression> 
    </element> 
</element> 

我不得不爲每個表達式類型添加分配(Object_Text,Object_Heading,... )添加到下一個父代的標記包含標記的容器節點(並非所有容器都具有該標記,應忽略這些標記),並且表達式的上下文值必須符合容器的句柄值。由於我需要爲每個表達式類型分配一個事實,因此無論它出現的多少,我都應該爲其上下文中的每個類型分配一個分配。所以期望的輸出是:

<?xml version="1.0" encoding="UTF-8"?> 
<element tag="container"> 
    <data handle="$1"> 
     ... 
    </data> 
    <assignments> <!--Added assignments here (one for each type with @context='$1')--> 
     <assignment name="Object_Text"> 
     </assignment> 
     <assignment name="Object_Heading"> 
     </assignment> 
     <assignment name="Object_Identifier"> 
     </assignment> 
    </assignments> 
    <expression context="$1"> 
     Object_Text 
    </expression> 
    <expression context="$1"> 
     Object_Text 
    </expression> 
    <expression context="$1"> 
     Object_Heading 
    </expression> 
    <element tag="container"> 
     <data handle="$2"> 
      ... 
     </data> 
     <assignments/> 
     <element tag="container"> 
      <data handle="$3"> 
       ... 
      </data> 
      <assignments> <!--Added assignments here (one for each type with @context='$3')--> 
       <assignment name="Object_Text"> 
       </assignment> 
      </assignments> 
      <expression context="$3"> 
       Object_Text 
      </expression> 
     </element> 
     <element tag="container"> 
      ... 
     </element> 
    </element> 

    <element tag="container"> 
    <expression context="$1"> 
     Object_Identifier 
    </expression> 
    </element> 
</element> 

目前我能得到一組表達型的(Object_Text等)Muenchian分組的方法。但我的問題是,我無法通過它們的屬性@context區分這些表達式類型,因此容器只包含正確表達式的賦值,而它正是包含在相同的@context中。

我很感激任何幫助。有人知道達到預期輸出的方法嗎?我嘗試了很多東西,但目前缺乏這方面的經驗/知識。

編輯:它應該被添加,這是一個XML文檔的示例結構。因此,xslt函數應該可以識別任意嵌套的,被包裝的結構中的表達式並且可以多次。

回答

0

讓我們通過下assignments節點宣佈爲表達

<xsl:key name="kExp" match="expression" use="concat(@context, '|', normalize-space(.))"/> 

一鍵啓動,我們將會把第一前同輩節點data

<xsl:variable name="dataHandle" select="preceding-sibling::data/@handle"/> 

當此的@handle屬性變量用於assignments節點並使用Muenchian方法()我假設expre ssions是兄弟姐妹或assignments節點)的兄弟姐妹的後代:

<xsl:template match="assignments"> 
     <xsl:variable name="dataHandle" select="preceding-sibling::data/@handle"/> 
     <xsl:copy> 
      <xsl:for-each select="../descendant::expression[@context=$dataHandle 
            and generate-id()=generate-id(key('kExp', concat(@context, '|', normalize-space(.)))[1])]"> 
       <assignment name="{normalize-space(.)}"></assignment> 
      </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

整個樣式表是如下:

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

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

    <xsl:key name="kExp" match="expression" use="concat(@context, '|', normalize-space(.))"/> 


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

    <xsl:template match="assignments"> 
     <xsl:variable name="dataHandle" select="preceding-sibling::data/@handle"/> 
     <xsl:copy> 
      <xsl:for-each select="../descendant::expression[@context=$dataHandle 
            and generate-id()=generate-id(key('kExp', concat(@context, '|', normalize-space(.)))[1])]"> 
       <assignment name="{normalize-space(.)}"></assignment> 
      </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

看到它的行動在http://xsltransform.net/a9Giwr

+0

謝謝你的回答,這真的幫助了我,讓我有了正確的提示來推進我的工作! –

0

這會讓你走。你有一些壓制,這個代碼沒有考慮。

<!-- Handle each container that has an assignments node. --> 
    <xsl:template match="element[@tag='container' and .//assignments]"> 
    <!-- Bind to the expressions for this container. --> 
    <xsl:variable name="expressions" select="expression"/> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"> 
     <xsl:with-param name="expressions" select="$expressions"/> 
     </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

    <!-- Create the assignments for each container. --> 
    <xsl:template match="assignments"> 
    <xsl:param name="expressions"/> 
    <xsl:copy> 
     <xsl:for-each select="$expressions"> 
     <xsl:element name="assignment"> 
      <xsl:attribute name="name"> 
      <xsl:value-of select="normalize-space(.)"/> 
      </xsl:attribute> 
     </xsl:element> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

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