XSLT 1.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函数应该可以识别任意嵌套的,被包装的结构中的表达式并且可以多次。
答
让我们通过下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。
答
这会让你走。你有一些压制,这个代码没有考虑。
<!-- 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>
谢谢你的回答,这真的帮助了我,让我有了正确的提示来推进我的工作! –