次のようなXMLがあります-
<autnresponse>
<responsedata>
<autn:hit>
<autn:content>
<DOCUMENT>
<DRETITLE>Request Audio Visual Services</DRETITLE>
<HIERARCHY>LEVEL1:8+My Workplace#4~LEVEL2:33+Meetings~LEVEL3:151+Book meeting room~</HIERARCHY>
<HIERARCHY>LEVEL1:8+My Workplace#4~LEVEL2:33+Meetings~LEVEL3:154+Support for Meeting Room Equipment~</HIERARCHY>
</DOCUMENT>
</autn:content>
</autn:hit>
<autn:hit>
<autn:content>
<DOCUMENT>
<DRETITLE>View outage calendar for SAP ICERPS system</DRETITLE>
<HIERARCHY>LEVEL1:4+IT Services & Access#1~LEVEL2:8+IT for IT~LEVEL3:45+SAP Services~</HIERARCHY>
<HIERARCHY>LEVEL1:4+IT Services & Access#1~LEVEL2:21+Corp and Consumer Systems~LEVEL3:85+Market and Sell systems~</HIERARCHY>
<HIERARCHY>LEVEL1:4+IT Services & Access#1~LEVEL2:23+Support Function Systems~LEVEL3:128+SAP Systems~</HIERARCHY>
<HIERARCHY>LEVEL1:4+IT Services & Access#1~LEVEL2:23+Support Function Systems~LEVEL3:129+Supply Chain Planning Services Systems ~</HIERARCHY>
</DOCUMENT>
</autn:content>
</autn:hit>
</responsedata>
</autnresponse>
level1~level2~level3の連結文字列である複数の階層要素があることに注意してください。各レベルは、LEVEL:LevelID+LevelName の形式です。LEVEL1 には、ソートする # のような追加の値があります。基本的に、この # 番号と他のレベルですべての level1 をアルファベット順に並べ替える必要があります。
私はこれをこのようなものに変換しようとしています -
<TREE>
<LEVEL1 name="IT Services & Access" id="4">
<LEVEL2 name="Corp and Consumer Systems" id="21">
<LEVEL3 name="Market and Sell systems" id="85">
<ITEM id="1000" name="View outage calendar for SAP ICERPS system">
</ITEM>
</LEVEL3>
</LEVEL2>
<LEVEL2 name="IT for IT" id="8">
<LEVEL3 name="SAP Services" id="45">
<ITEM id="1000" name="View outage calendar for SAP ICERPS system"></ITEM>
</LEVEL3>
</LEVEL2>
<LEVEL2 name="Support Function Systems" id="23">
<LEVEL3 name="SAP Systems" id="128">
<ITEM id="1000" name="View outage calendar for SAP ICERPS system">
</ITEM>
</LEVEL3>
<LEVEL3 name="Supply Chain Planning Services Systems " id="129">
<ITEM id="1000" name="View outage calendar for SAP ICERPS system">
</ITEM>
</LEVEL3>
</LEVEL2>
</LEVEL1>
<LEVEL1 name="My Workplace" id="8">
<LEVEL2 name="Meetings" id="33">
<LEVEL3 name="Book meeting room" id="151">
<ITEM id="100" name="Request Audio Visual Services"></ITEM>
</LEVEL3>
<LEVEL3 name="Support for Meeting Room Equipment" id="154">
<ITEM id="100" name="Request Audio Visual Services"></ITEM>
</LEVEL3>
</LEVEL2>
</LEVEL1>
</TREE>
基本的に、各 DOCUMENT には複数の階層が関連付けられています。それらをグループ化し、各レベルもグループ化する必要があります。
動作する私のXSLは次のようになります-
<?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:strip-space elements="*"/>
<xsl:key name="TOPLEVEL" match="autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY" use="substring-before(substring-after(.,'LEVEL1:'),'#')"/>
<xsl:key name="MIDLEVEL" match="autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY" use="substring-before(substring-after(.,'LEVEL2:'),'~')"/>
<xsl:key name="BOTTOMLEVEL" match="autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY" use="substring-before(substring-after(.,'LEVEL3:'),'~')"/>
<xsl:template match="/">
<TREE>
<xsl:for-each select="autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY[generate-id() = generate-id(key('TOPLEVEL',substring-before(substring-before(substring-after(.,'LEVEL1:'),'~'),'#') )[1])]">
<xsl:sort select="substring-after(substring-before(substring-after(.,'LEVEL1:'),'~'),'#')"/>
<xsl:variable name="TOP" select="substring-before(substring-after(.,'LEVEL1:'),'#')"/>
<LEVEL1>
<xsl:attribute name="name"><xsl:value-of select="substring-after($TOP,'+')"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="substring-before($TOP,'+')"/></xsl:attribute>
<xsl:for-each select="//autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY[substring-before(substring-after(.,'LEVEL1:'),'#')=$TOP and generate-id() = generate-id(key('MIDLEVEL',substring-before(substring-after(.,'LEVEL2:'),'~') )[1])]">
<xsl:sort select="substring-after(substring-before(substring-after(.,'LEVEL2:'),'~'),'+')"/>
<xsl:variable name="MID" select="substring-before(substring-after(.,'LEVEL2:'),'~')"/>
<LEVEL2>
<xsl:attribute name="name"><xsl:value-of select="substring-after($MID,'+')"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="substring-before($MID,'+')"/></xsl:attribute>
<xsl:for-each select="//autnresponse/responsedata/autn:hit/autn:content/DOCUMENT/HIERARCHY[substring-before(substring-after(.,'LEVEL1:'),'#')=$TOP and substring-before(substring-after(.,'LEVEL2:'),'~')=$MID and generate-id() = generate-id(key('BOTTOMLEVEL',substring-before(substring-after(.,'LEVEL3:'),'~') )[1])]">
<xsl:sort select="substring-after(substring-before(substring-after(.,'LEVEL3:'),'~'),'+')"/>
<xsl:variable name="BOTTOM" select="substring-before(substring-after(.,'LEVEL3:'),'~')"/>
<LEVEL3>
<xsl:attribute name="name"><xsl:value-of select="substring-after($BOTTOM,'+')"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="substring-before($BOTTOM,'+')"/></xsl:attribute>
<xsl:apply-templates select="//HIERARCHY[substring-before(substring-after(.,'LEVEL1:'),'#')=$TOP and substring-before(substring-after(.,'LEVEL2:'),'~')=$MID and substring-before(substring-after(.,'LEVEL3:'),'~')=$BOTTOM]">
<xsl:sort select="../DREDRETITLE"/>
</xsl:apply-templates>
</LEVEL3>
</xsl:for-each>
</LEVEL2>
</xsl:for-each>
</LEVEL1>
</xsl:for-each>
</TREE>
</xsl:template>
<xsl:template match="HIERARCHY">
<ITEM>
<xsl:attribute name="id"><xsl:value-of select="../ID"/></xsl:attribute>
<xsl:attribute name="name"><xsl:value-of select="../DREDRETITLE"/></xsl:attribute>
</ITEM>
</xsl:template>
</xsl:stylesheet>
これでのパフォーマンスは良くなく、最善の解決策ではないと感じています. これに対して、より高速に機能するより良い代替ソリューションがあるかどうか疑問に思います。基本的に、1200 以上の DOCUMENT 要素があり、XSL 変換には約 15 秒かかります