1

組織階層を持つ XML 構造があります。要素は orgの<pkEntity>親 ID であり、org<entityParent>の子です。親子コンビの奥深さがわからない。以下の状態に変換する必要があります。

 <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>
4

1 に答える 1

2

XSLT 1.0 (および XSLT 2.0) ソリューション

<xsl:key> を使用して親と子を配置し、ソリューションのパフォーマンスを向上させることに基づいています。

<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>

編集: 各子に対して新しい <client:children> が作成され、その動作は <for-each> ループのコードを調整することで変更できると想定しました。

于 2013-02-19T16:44:31.620 に答える