我是xslt的新手,因此无法理解这里为我想要实现的目标提供的复杂解决方案。以非Muenchian方式对繁重的数据结构进行分组(意味着有很多属性和元素,因此不能使用任何串联的解决方案)。因为我觉得大数据的串联会影响性能。这是我尝试过的示例输入数据、所需输出和 xsl:
#输入 xml #
<out:OuterSegment>
<out:Segment >
<out:from Code="CHN"/>
<out:tothis Code="HYD"/>
<out:group>0</out:group>
</out:Segment>
<out:Segment >
<out:from Code="HYD"/>
<out:tothis Code="BLR"/>
<out:group>1</out:group>
</out:Segment>
<out:Segment >
<out:from Code="BLR"/>
<out:tothis Code="TVN"/>
<out:group>2</out:group>
</out:Segment>
<out:Segment >
<out:from Code="TVN"/>
<out:tothis Code="DEL"/>
<out:group>2</out:group>
</out:Segment>
</out:OuterSegment>
输出 XML
<out2:OuterSegment>
<out2:Segment >
<out2:from Code="CHN"/>
<out2:tothis Code="HYD"/>
<out2:group>0</out2:group>
</out2:Segment>
</out2:OuterSegment>
<out2:OuterSegment>
<out2:Segment >
<out2:from Code="HYD"/>
<out2:tothis Code="BLR"/>
<out2:group>1</out2:group>
</out2:Segment>
</out2:OuterSegment>
<out2:OuterSegment>
<out2:Segment >
<out2:from Code="BLR"/>
<out2:tothis Code="TVN"/>
<out2:group>2</out2:group>
</out2:Segment>
</out2:OuterSegment>
<out2:OuterSegment>
<out2:Segment >
<out2:from Code="TVN"/>
<out2:tothis Code="DEL"/>
<out2:group>2</out2:group>
</out2:Segment>
</out2:OuterSegment>
XSL 代码段
<xsl:choose>
<xsl:when test="position() = 1">
<xsl:message> its the first row </xsl:message>
<out:OuterSegment>
<xsl:apply-templates select="in2:IncomingSegment"
mode="localIncomingSegmentRefToSegment" />
</out:OuterSegment>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="prevgroup" select="//in2:IncomingSegment[position() - 1]/@Group"/>
<xsl:message> is the subsequent row</xsl:message>
<xsl:if test="$prevgroup = //in2:IncomingSegment[$prevgroup]/@Group">
<xsl:apply-templates select="in2:IncomingSegment"
mode="localIncomingSegmentRefToSegment" />
</xsl:if>
<xsl:if test="$prevgroup != //in2:IncomingSegment[$prevgroup]/@Group">
<out:OuterSegment>
<xsl:apply-templates select="in2:IncomingSegment"
mode="SegmentRefToSegment" />
</out:OuterSegment>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
我需要提到,上面的输入xml是由另一个xslt生成的,其输入为:
实际输入 xml
<in:RefSegment key="1" group="0">
<in:inSegment >
<in:from Code="CHN"/>
<in:tothis Code="HYD"/>
</in:inSegment>
</in:RefSegment>
<in:RefSegment key="2" group="1">
<in:inSegment >
<in:from Code="HYD"/>
<in:tothis Code="BLR"/>
</in:inSegment>
</in:RefSegment>
<in:RefSegment key="3" group="2">
<in:inSegment >
<in:from Code="BLR"/>
<in:tothis Code="TVN"/>
</in:inSegment>
</in:RefSegment>
<in:RefSegment key="4" group="2">
<in:inSegment >
<in:from Code="TVN"/>
<in:tothis Code="BLR"/>
</in:inSegment>
</in:RefSegment>
<in:DataSegments>
<in:Data >
<in:keyref> 0 </in:keyref>
</in:Data>
<in:Data >
<in:keyref> 1 </in:keyref>
</in:Data>
<in:Data >
<in:keyref> 2 </in:keyref>
</in:Data>
<in:Data >
<in:keyref> 2 </in:keyref>
</in:Data>
<in:DataSegments>
是否可以一次性从上述实际输入中获得最终输出.xml.xml ?
您如何处理有关in
和out2
前缀的输入和输出xml的命名空间,以及命名空间是否是一个问题,所以也许这种方法没有用,但我想分享这个想法。
这是基于以下假设:所有 <in:Data>
节点位于与实际输入 XML 所建议的<in:RefSegment>
相对应的位置 - 如果不是这种情况,请将其添加到您的问题中,因为有必要按<in:RefSegment>
的 group
属性值和相应的<in:keyref>
值进行分组。
作为对输入 XML 代码段的调整,我将<in:RefSegment>
节点包装在具有示例命名空间的根节点中:<root xmlns:in="http://www.example.com">
并将示例命名空间xmlns:in="http://www.example.com"
和xmlns:out2="http://www.example2.com"
添加到样式表声明中。由于命名空间xmlns:out2
,此命名空间将添加到每个out2:OuterSegment
节点。
遵循 XSLT
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:in="http://www.example.com" xmlns:out2="http://www.example2.com"
exclude-result-prefixes="in" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="in:RefSegment">
<xsl:variable name="position" select="position()"/>
<out2:OuterSegment>
<out2:Segment>
<out2:from>
<xsl:attribute name="Code">
<xsl:value-of select="in:inSegment/in:from/@Code" />
</xsl:attribute>
</out2:from>
<out2:tothis Code="HYD">
<xsl:attribute name="Code">
<xsl:value-of select="in:inSegment/in:tothis/@Code" />
</xsl:attribute>
</out2:tothis>
<out2:group>
<xsl:value-of select="normalize-space(//in:DataSegments/in:Data[$position]/in:keyref)"/>
</out2:group>
</out2:Segment>
</out2:OuterSegment>
</xsl:template>
<xsl:template match="in:DataSegments"/>
</xsl:transform>
当应用于实际输入 XML 并调整缺失的结束</in:DataSegments>
时,会产生以下结果:
<out2:OuterSegment xmlns:out="http://www.example2.com">
<out2:Segment>
<out2:from Code="CHN"/>
<out2:tothis Code="HYD"/>
<out2:group>0</out2:group>
</out2:Segment>
</out2:OuterSegment>
<out2:OuterSegment xmlns:out="http://www.example2.com">
<out2:Segment>
<out2:from Code="HYD"/>
<out2:tothis Code="BLR"/>
<out2:group>1</out2:group>
</out2:Segment>
</out2:OuterSegment>
<out2:OuterSegment xmlns:out="http://www.example2.com">
<out2:Segment>
<out2:from Code="BLR"/>
<out2:tothis Code="TVN"/>
<out2:group>2</out2:group>
</out2:Segment>
</out:OuterSegment>
<out:OuterSegment xmlns:out="http://www.example2.com">
<out2:Segment>
<out2:from Code="TVN"/>
<out2:tothis Code="BLR"/>
<out2:group>2</out2:group>
</out2:Segment>
</out2:OuterSegment>
in:RefSegment
节点匹配的模板<xsl:template match="in:RefSegment">
生成<out2:OuterSegment>
节点。<xsl:variable name="position" select="position()"/>
是当前在:RefSegment中的位置。
生成的out2:from
和out2:tothis
节点的属性是从当前处理的in:RefSegment
中检索的:
<out2:from>
<xsl:attribute name="Code">
<xsl:value-of select="in:inSegment/in:from/@Code" />
</xsl:attribute>
</out2:from>
以及从位于同一位置的in:Data
节点检索out2:group
的值:
<out2:group>
<xsl:value-of select="normalize-space(//in:DataSegments
/in:Data[$position/in:keyref)"/>
</out2:group>
使用额外的normalize-space()
来删除输入中的空间。
模板匹配in:DataSegments
<xsl:template match="in:DataSegments"/>
为空,因此in:DataSegments
节点将从输出中删除。