2017-04-26 57 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>