2

次のようなXMLがあります-

<resultset>
    <hit>
        <content>
            <ITEM>
                <TITLE>Office Cleaning</TITLE>
                <DESCRIPTION>blah blah blah</DESCRIPTION>
                <Hierarchy>level1A:level2A:level3A</Hierarchy>
                <Hierarchy>level1B:level2B:level3B</Hierarchy>
            </ITEM>
        </content>
    </hit>
    <hit>
        <content>
            <ITEM>
                <TITLE>Office Cleaning1</TITLE>
                <DESCRIPTION>blah blah blah</DESCRIPTION>
                <Hierarchy>level1A:level2A:level3A</Hierarchy>
            </ITEM>
        </content>
    </hit>
    <hit>
        <content>
            <ITEM>
                <TITLE>Office Cleaning2</TITLE>
                <DESCRIPTION>blah blah blah</DESCRIPTION>
                <Hierarchy>level1A:level2B:level3C</Hierarchy>
            </ITEM>
        </content>
    </hit>
</resultset>

level1:level2:level3 の連結された文字列である複数の階層要素があることに注意してください。これを次のようなものに変換しようとしています-

<TREE>
<LEVELS>
<LEVEL1 name="level1A">
 <LEVEL2 name="level2A">
   <LEVEL3 name="level3A">
      <ITEM Name="Office Cleaning"/>
      <ITEM Name="Office Cleaning1"/>
   </LEVEL3>
 </LEVEL2>
</LEVEL1>
<LEVEL1 name="level1B">
 <LEVEL2 name="level2B">
   <LEVEL3 name="level3B">
        <ITEM Name="Office Cleaning"/>
   </LEVEL3>
 </LEVEL2>
</LEVEL1>
<LEVEL1 name="level1A">
 <LEVEL2 name="level2B">
   <LEVEL3 name="level3C">
      <ITEM Name="Office Cleaning2"/>
    </LEVEL3>
 </LEVEL2>
</LEVEL1>
</LEVELS>
</TREE>

基本的に、各アイテムには複数の階層が関連付けられています。それらをグループ化する必要があります。

私が得たのは -

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:autn="http://schemas.autonomy.com/aci/">

<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:key name="HIERARCHYLEVELS" match="resultset/hit/content/ITEM" use="HIERARCHY" />
<xsl:template match="/">
<TREE>

    <xsl:for-each select="resultset/hit/content/ITEM[generate-id()=generate-id(key('HIERARCHYLEVELS', HIERARCHY)[1])]">
        <xsl:for-each select="HIERARCHY">
        <xsl:variable name="level" select="HIERARCHY"/>
        <HIERARCHY name="{$level}" >

            <xsl:variable name="name" select="TITLE"/>

            <ITEM name="{$name}"/>

        </HIERARCHY>
        </xsl:for-each>
    </xsl:for-each>


</TREE>
</xsl:template>

</xsl:stylesheet>

しかし問題は、最初に一致した階層タグしか取得できないことです。たとえば、「オフィスクリーニング1」が表示されません。すべての階層要素が考慮されるようにするにはどうすればよいですか? 私はまだそれをさまざまなレベルに分割する必要があります。

4

2 に答える 2

0

この変換:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kItemByHier" match="ITEM" use="Hierarchy"/>
 <xsl:key name="kHierByVal" match="Hierarchy" use="."/>

 <xsl:template match="/*">
     <xsl:apply-templates select=
     "*/*/*/Hierarchy[generate-id()=generate-id(key('kHierByVal',.)[1])]"/>
 </xsl:template>

  <xsl:template match="Hierarchy">
    <xsl:call-template name="makeTree">
      <xsl:with-param name="pHier" select="string()"/>
      <xsl:with-param name="pItems" select="key('kItemByHier', .)"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="makeTree">
    <xsl:param name="pHier"/>
    <xsl:param name="pDepth" select="1"/>
    <xsl:param name="pItems" select="/.."/>

    <xsl:choose>
      <xsl:when test="not($pHier)">
        <xsl:for-each select="$pItems">
          <ITEM name="{TITLE}"/>
        </xsl:for-each>
      </xsl:when>
      <xsl:otherwise>
        <xsl:element name="LEVEL{$pDepth}">
          <xsl:attribute name="name">
            <xsl:value-of select="substring-before(concat($pHier,':'), ':')"/>
          </xsl:attribute>

          <xsl:call-template name="makeTree">
            <xsl:with-param name="pHier" 
                            select="substring-after($pHier,':')"/>
            <xsl:with-param name="pDepth" select="$pDepth+1"/>
            <xsl:with-param name="pItems" select="$pItems"/>
          </xsl:call-template>
        </xsl:element>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

提供された XML ドキュメントに適用した場合:

<resultset>
    <hit>
        <content>
            <ITEM>
                <TITLE>Office Cleaning</TITLE>
                <DESCRIPTION>blah blah blah</DESCRIPTION>
                <Hierarchy>level1A:level2A:level3A</Hierarchy>
                <Hierarchy>level1B:level2B:level3B</Hierarchy>
            </ITEM>
        </content>
    </hit>
    <hit>
        <content>
            <ITEM>
                <TITLE>Office Cleaning1</TITLE>
                <DESCRIPTION>blah blah blah</DESCRIPTION>
                <Hierarchy>level1A:level2A:level3A</Hierarchy>
            </ITEM>
        </content>
    </hit>
    <hit>
        <content>
            <ITEM>
                <TITLE>Office Cleaning2</TITLE>
                <DESCRIPTION>blah blah blah</DESCRIPTION>
                <Hierarchy>level1A:level2B:level3C</Hierarchy>
            </ITEM>
        </content>
    </hit>
</resultset>

必要な正しい結果が生成されます

<LEVEL1 name="level1A">
   <LEVEL2 name="level2A">
      <LEVEL3 name="level3A">
         <ITEM name="Office Cleaning"/>
         <ITEM name="Office Cleaning1"/>
      </LEVEL3>
   </LEVEL2>
</LEVEL1>
<LEVEL1 name="level1B">
   <LEVEL2 name="level2B">
      <LEVEL3 name="level3B">
         <ITEM name="Office Cleaning"/>
      </LEVEL3>
   </LEVEL2>
</LEVEL1>
<LEVEL1 name="level1A">
   <LEVEL2 name="level2B">
      <LEVEL3 name="level3C">
         <ITEM name="Office Cleaning2"/>
      </LEVEL3>
   </LEVEL2>
</LEVEL1>
于 2012-10-23T04:00:31.947 に答える
0

参考までに、ここに解決策の草案を示します。出力からわかるように、異なるグループ化ルールを使用しているため、近いですが、静かではありません。必要なグループ化ルールを理解しようとしています。理解が深まったら更新します。

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  exclude-result-prefixes="xsl exsl">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:variable name="phase-1-output">
  <xsl:apply-templates select="/" mode="phase-1" />
</xsl:variable>

<xsl:variable name="phase-2-output">
  <xsl:apply-templates select="exsl:node-set($phase-1-output)" mode="phase-2" />
</xsl:variable>

<xsl:template match="/">
  <xsl:copy-of select="$phase-2-output" />
</xsl:template>

<!--================ Phase 1 ===============================-->    
 <xsl:template match="/" mode="phase-1">
   <t>
     <xsl:apply-templates select="*/*/*/ITEM/Hierarchy" mode="phase-1" />
   </t>
 </xsl:template>

 <xsl:template match="Hierarchy" mode="phase-1">
   <xsl:call-template name="analyze-hierarchy">
     <xsl:with-param name="levels" select="." />
     <xsl:with-param name="item" select="../TITLE" />
   </xsl:call-template>  
 </xsl:template>

<xsl:template name="analyze-hierarchy"><!-- phase-1 -->
  <xsl:param name="levels" />
  <xsl:param name="item" />
  <xsl:variable name="level" select="substring-before(concat($levels,':'),':')" />
  <xsl:variable name="e-level" select="
    translate(
      substring($level,1,string-length($level) - 1),
      'abcdefghijklmnopqrstuvwxyz',
      'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
  <xsl:choose>
    <xsl:when test="$level">
      <xsl:element name="{$e-level}">
        <xsl:attribute name="name"><xsl:value-of select="$level" /></xsl:attribute>  
        <xsl:call-template name="analyze-hierarchy">
         <xsl:with-param name="levels" select="substring-after($levels,':')" />
         <xsl:with-param name="item" select="$item" />
        </xsl:call-template>  
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <ITEM Name="{$item}"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>  

<!--================ Phase 2 ===============================-->    
<xsl:key name="kLevel"
   match="*[starts-with(name(),'LEVEL')]"
   use="concat(generate-id(..),'|',@name)" />

 <xsl:template match="/" mode="phase-2">
  <TREE>
    <LEVELS>
      <xsl:variable name="t" select="concat(generate-id(t),'|')" />
      <xsl:apply-templates select="t/LEVEL1[
      generate-id() = generate-id( key('kLevel',concat($t,@name))[1])
      ]" mode="phase-2-head" />
    </LEVELS>  
  </TREE>  
</xsl:template>

<xsl:template match="*[starts-with(name(),'LEVEL')]" mode="phase-2-head">
  <xsl:copy>
    <xsl:copy-of select="@*" />
    <xsl:apply-templates select="key('kLevel',concat(generate-id(..),'|',@name))"  mode="phase-2" />
    <xsl:copy-of select="ITEM" />
   </xsl:copy>
 </xsl:template>   

 <xsl:template match="*[starts-with(name(),'LEVEL')]" mode="phase-2">
      <xsl:variable name="p" select="concat(generate-id(.),'|')" />
      <xsl:apply-templates select="*[starts-with(name(),'LEVEL')][
      generate-id() = generate-id( key('kLevel',concat($p,@name))[1])
      ]" mode="phase-2-head" />
 </xsl:template>   

</xsl:stylesheet>

...サンプル入力でこれが生成されます(静かで正しい出力ではありません)...

<TREE>
  <LEVELS>
    <LEVEL1 name="level1A">
      <LEVEL2 name="level2A">
        <LEVEL3 name="level3A">
          <ITEM Name="Office Cleaning" />
        </LEVEL3>
      </LEVEL2>
      <LEVEL2 name="level2A">
        <LEVEL3 name="level3A">
          <ITEM Name="Office Cleaning1" />
        </LEVEL3>
      </LEVEL2>
      <LEVEL2 name="level2B">
        <LEVEL3 name="level3C">
          <ITEM Name="Office Cleaning2" />
        </LEVEL3>
      </LEVEL2>
    </LEVEL1>
    <LEVEL1 name="level1B">
      <LEVEL2 name="level2B">
        <LEVEL3 name="level3B">
          <ITEM Name="Office Cleaning" />
        </LEVEL3>
      </LEVEL2>
    </LEVEL1>
  </LEVELS>
</TREE>

アップデート

OK、ラウンド 2 です。Dimitre のグループ化ルールをコピーしました。これは、Hierarchy 要素の内容に関してすべてかゼロかです。このソリューションは、サンプル入力に対して期待される出力を生成します。Dimitre の<xsl:element name="LEVEL{$pDepth}">方法とは対照的に、階層の手順から LEVEL1 スタイルの要素名を派生させたことに注意してください。これが正しいかどうかはわかりません。

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:key name="kLevel" match="Hierarchy" use="." />

<xsl:template match="/">
  <TREE>
    <LEVELS>
     <xsl:apply-templates select="*/*/*/ITEM/Hierarchy[
        generate-id() = generate-id( key('kLevel',.)[1])
      ]" mode="group" />
    </LEVELS>
   </TREE>
</xsl:template>

 <xsl:template match="Hierarchy" mode="group">
   <xsl:call-template name="analyze-hierarchy">
     <xsl:with-param name="key" select="." />
     <xsl:with-param name="levels" select="." />
   </xsl:call-template>  
 </xsl:template>

<xsl:template name="analyze-hierarchy">
  <xsl:param name="key" />
  <xsl:param name="levels" />
  <xsl:variable name="level" select="substring-before(concat($levels,':'),':')" />
  <xsl:variable name="e-level" select="
    translate(
      substring($level,1,string-length($level) - 1),
      'abcdefghijklmnopqrstuvwxyz',
      'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
  <xsl:choose>
    <xsl:when test="$level">
      <xsl:element name="{$e-level}">
        <xsl:attribute name="name"><xsl:value-of select="$level" /></xsl:attribute>  
        <xsl:call-template name="analyze-hierarchy">
         <xsl:with-param name="key" select="$key" />
         <xsl:with-param name="levels" select="substring-after($levels,':')" />
        </xsl:call-template>  
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="key('kLevel',$key)" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>  

<xsl:template match="Hierarchy">
  <ITEM Name="{../TITLE}" />
</xsl:template>

</xsl:stylesheet>
于 2012-10-23T04:52:10.253 に答える