我有一个带有组织层次结构的XML结构。 <pkEntity>
元素是org的父ID,<entityParent>
是org的子ID。我不知道父/子组合的深度。我需要改变下面提到的状态:
<EntityDimCollection>
<EntityDim>
<pkEntity>-9</pkEntity>
<entityParent>-7</entityParent>
<entityCode>Own_CP</entityCode>
<entityType>OT</entityType>
<essEntityCode>un.Own_CP</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>-8</pkEntity>
<entityParent>-7</entityParent>
<entityCode>Alternatives</entityCode>
<entityType>OT</entityType>
<essEntityCode>un.Alternatives</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>8555</pkEntity>
<entityParent>-8</entityParent>
<entityCode>Ex_BABRO</entityCode>
<entityType>CF</entityType>
<essEntityCode>un.Ex_BABRO</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>8752</pkEntity>
<entityParent>-8</entityParent>
<entityCode>Ex_SY</entityCode>
<entityType>CF</entityType>
<essEntityCode>un.Ex_SY</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>9731</pkEntity>
<entityParent>-8</entityParent>
<entityCode>NOR</entityCode>
<entityType>LE</entityType>
<essEntityCode>un.NOR</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>1649940</pkEntity>
<entityParent>9731</entityParent>
<entityCode>NO</entityCode>
<entityType>CG</entityType>
<essEntityCode>un.NOR.NO</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>1838293</pkEntity>
<entityParent>1649940</entityParent>
<entityCode>UKONORWAY</entityCode>
<entityType>CG</entityType>
<essEntityCode>un.NOR.UKONORWAY</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>1127251</pkEntity>
<entityParent>1838293</entityParent>
<entityCode>2BUS</entityCode>
<entityType>CG</entityType>
<essEntityCode>un.NOR.2BUS</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>1127274</pkEntity>
<entityParent>1127251</entityParent>
<entityCode>3BUS_B</entityCode>
<entityType>CG</entityType>
<essEntityCode>un.NOR.3BUS_B</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>1988187</pkEntity>
<entityParent>1127274</entityParent>
<entityCode>4BUS_B</entityCode>
<entityType>CG</entityType>
<essEntityCode>un.NOR.4BUS_B</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>1988188</pkEntity>
<entityParent>1988187</entityParent>
<entityCode>5ADM_B</entityCode>
<entityType>CG</entityType>
<essEntityCode>un.NOR.5ADM_B</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>1988189</pkEntity>
<entityParent>1988187</entityParent>
<entityCode>5FVK_B</entityCode>
<entityType>CG</entityType>
<essEntityCode>un.NOR.5FVK_B</essEntityCode>
</EntityDim>
<EntityDim>
<pkEntity>1988190</pkEntity>
<entityParent>1988189</entityParent>
<entityCode>61_FVK_B</entityCode>
<entityType>CG</entityType>
<essEntityCode>un.NOR.61_FVK_B</essEntityCode>
</EntityDim>
</EntityDimCollection>
并且使用Mark Veenstra解决方案我得到了像这样的输出
<?xml version="1.0" encoding="UTF-8"?>
<client:LMSDetails xmlns:client="http://foo/bar">
<client:ParentID>-9</client:ParentID>
<client:ChildID>-7</client:ChildID>
<client:name/>
<client:identifier>OT</client:identifier>
<client:isActive/>
<client:ParentID>-8</client:ParentID>
<client:ChildID>-7</client:ChildID>
<client:name/>
<client:identifier>OT</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>8555</client:ParentID>
<client:ChildID>-8</client:ChildID>
<client:name/>
<client:identifier>CF</client:identifier>
<client:isActive/>
</client:children>
<client:children>
<client:ParentID>8752</client:ParentID>
<client:ChildID>-8</client:ChildID>
<client:name/>
<client:identifier>CF</client:identifier>
<client:isActive/>
</client:children>
<client:children>
<client:ParentID>9731</client:ParentID>
<client:ChildID>-8</client:ChildID>
<client:name/>
<client:identifier>LE</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1649940</client:ParentID>
<client:ChildID>9731</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1838293</client:ParentID>
<client:ChildID>1649940</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1127251</client:ParentID>
<client:ChildID>1838293</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1127274</client:ParentID>
<client:ChildID>1127251</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1988187</client:ParentID>
<client:ChildID>1127274</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1988188</client:ParentID>
<client:ChildID>1988187</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
</client:children>
<client:children>
<client:ParentID>1988189</client:ParentID>
<client:ChildID>1988187</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1988190</client:ParentID>
<client:ChildID>1988189</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
</client:children>
</client:children>
</client:children>
</client:children>
</client:children>
</client:children>
</client:children>
</client:children>
<client:ParentID>8555</client:ParentID>
<client:ChildID>-8</client:ChildID>
<client:name/>
<client:identifier>CF</client:identifier>
<client:isActive/>
<client:ParentID>8752</client:ParentID>
<client:ChildID>-8</client:ChildID>
<client:name/>
<client:identifier>CF</client:identifier>
<client:isActive/>
<client:ParentID>9731</client:ParentID>
<client:ChildID>-8</client:ChildID>
<client:name/>
<client:identifier>LE</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1649940</client:ParentID>
<client:ChildID>9731</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1838293</client:ParentID>
<client:ChildID>1649940</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1127251</client:ParentID>
<client:ChildID>1838293</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1127274</client:ParentID>
<client:ChildID>1127251</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1988187</client:ParentID>
<client:ChildID>1127274</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1988188</client:ParentID>
<client:ChildID>1988187</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
</client:children>
<client:children>
<client:ParentID>1988189</client:ParentID>
<client:ChildID>1988187</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
<client:children>
<client:ParentID>1988190</client:ParentID>
<client:ChildID>1988189</client:ChildID>
<client:name/>
<client:identifier>CG</client:identifier>
<client:isActive/>
</client:children>
</client:children>
</client:children>
</client:children>
</client:children>
</client:children>
</client:children>
</client:LMSDetails>
答案 0 :(得分:2)
XSLT 1.0(和XSLT 2.0)解决方案
它基于使用&lt; xsl:key&gt;安排父母和孩子,同时提高解决方案的表现。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:client="http://client.org">
<xsl:output method="xml" indent="yes" />
<!-- Use keys to boost performance -->
<xsl:key name="entity-key" match="EntityDim" use="pkEntity" />
<xsl:key name="parent-key" match="EntityDim" use="entityParent" />
<!-- Process root element -->
<xsl:template match="EntityDimCollection">
<client:LMSDetails>
<!-- Apply template to root entities, i.e. entities with no parent nodes -->
<xsl:apply-templates select="EntityDim[not(key('entity-key', entityParent))]" />
</client:LMSDetails>
</xsl:template>
<!-- First one to use for the real parent -->
<xsl:template match="EntityDim">
<!-- Obtain the relevant information -->
<client:ParentID><xsl:value-of select="pkEntity" /></client:ParentID>
<client:ChildID><xsl:value-of select="entityParent" /></client:ChildID>
<client:name/>
<client:identifier><xsl:value-of select="entityType" /></client:identifier>
<client:isActive/>
<client:costCenter>
<!-- Obtain the expression after the last dot in essEntityCode -->
<xsl:call-template name="get-suffix">
<xsl:with-param name="text" select="essEntityCode" />
</xsl:call-template>
</client:costCenter>
<!-- Outputs the children for this node : we just search which entities have the
current pkEntity as their entityParent-->
<xsl:for-each select="key('parent-key', pkEntity)">
<client:children>
<xsl:apply-templates select="." />
</client:children>
</xsl:for-each>
</xsl:template>
<!-- Recursive template to obtain the suffix from essEntityCode (the part after
the last dot ) -->
<xsl:template name="get-suffix">
<xsl:param name="text" />
<!-- Check whether the current text contains a dot -->
<xsl:choose>
<!-- Case CONTAINS_DOT: recurse until there is not more dots in the string -->
<xsl:when test="contains($text, '.')">
<xsl:call-template name="get-suffix">
<xsl:with-param name="text" select="substring-after($text, '.')" />
</xsl:call-template>
</xsl:when>
<!-- Case WITHOUT_DOTS : output suffix -->
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
仅限XSLT 2.0解决方案
构建层次结构的方式是相同的,唯一的区别是从essEntityCode获取后缀的方式。在XSLT 1.0中,我们必须构建一个递归模板来检测最后一个点并提取后缀。但是在XSLT 2.0中,我们可以使用函数tokenize,它使用给定的正则表达式来分割给定的字符串。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:client="http://client.org">
<xsl:output method="xml" indent="yes" />
<xsl:key name="entity-key" match="EntityDim" use="pkEntity" />
<xsl:key name="parent-key" match="EntityDim" use="entityParent" />
<xsl:template match="EntityDimCollection">
<client:LMSDetails>
<xsl:apply-templates select="EntityDim[not(key('entity-key', entityParent))]" />
</client:LMSDetails>
</xsl:template>
<xsl:template match="EntityDim">
<client:ParentID><xsl:value-of select="pkEntity" /></client:ParentID>
<client:ChildID><xsl:value-of select="entityParent" /></client:ChildID>
<client:name/>
<client:identifier><xsl:value-of select="entityType" /></client:identifier>
<client:isActive/>
<client:costCenter>
<!-- This is the only difference from the XSLT 1.0 solution, instead
of calling the recursive template we tokenize the expression and
obtain the last element (which is the suffix) -->
<xsl:value-of select="tokenize(essEntityCode, '\.')[last()]" />
</client:costCenter>
<xsl:for-each select="key('parent-key', pkEntity)">
<client:children>
<xsl:apply-templates select="." />
</client:children>
</xsl:for-each>
</xsl:template>
</xsl:stelesheet>
编辑:我假设每个孩子都有一个新的&lt; client:children&gt;创建后,可以通过调整&lt; for-each&gt;中的代码来更改该行为。循环。