私は自分の質問に答えましたが、速度、明快さ、またはより慣用的な解決策のためにどのように改善できるかについて建設的なフィードバックをいただければ幸いです。:)
私の質問の元のコンテキストを理解したい場合は、〜編集〜にスキップするか、最後まで読んでください。
簡単に言えば、次のような XML データセットがあります。
<org> <!-- Organization -->
<dep> <!-- Department -->
<nm>Department</nm> <!-- Department Name -->
<emps> <!-- Head Department Employees -->
<emp> <!-- One of the Head Employees -->
<!-- Some Data, ie., L Name, F Name, and etc. (Omitted) -->
</emp>
<emp>
<!-- Omitted -->
</emp>
</emps>
<deps> <!-- So-called "Sub-Departments" -->
<dep>
<nm>Sub Department</nm>
<emps>
<emp>
<!-- Omitted -->
</emp>
</emps>
</dep>
</deps>
</dep>
</org>
これは非常に小さなサンプルですが、重要なことは、部門は任意の数の従業員と任意の数のサブ部門を持つことができるということです。通常、このようなデータセットは最下位に重く、トップ (リーダー) には少数の人がいて、サブ部門に進むにつれてますます多くの人がいます。私がやろうとしていたことは、実際には今日の半突破口で、その XML データセットを飾り気のない HTML 組織図に変換する方法を見つけ出すことです。
私が最初に思いついたのは、戦略的に配置された「float: left;」でネストされた div を吐き出すことでした。および「クリア: 両方;」スタイル、そして次のようになりました:
+-------------------------------------------------------+
| Dep |
| +------------------------+ |
| | +--------+ +---------+ | |
| | | Emp | | Emp | | |
| | +--------+ +---------+ | |
| +------------------------+ |
| +---------------------------------------------------+ |
| | +----------------------+ +----------------------+ | |
| | | Dep | | Dep | | |
| | | +--------+ +-------+ | | +--------+ +-------+ | | |
| | | | Emp | | Emp | | | | Emp | | Emp | | | |
| | | +--------+ +-------+ | | +--------+ +-------+ | | |
| | +----------------------+ +----------------------+ | |
| +---------------------------------------------------+ |
+-------------------------------------------------------+
私の粗雑な ASCII アートで申し訳ありません。
代わりに、これを生成できる XSLT 変換を考え出そうと頭を悩ませていました。
+-------------------------------------------------------+
| Dep |
| +------------------------+ |
| | +--------+ +---------+ | |
| | | Emp | | Emp | | |
| | +--------+ +---------+ | |
| +------------------------+ |
| +---------------------------------------------------+ |
| | +----------------------+ +----------------------+ | |
| | | Dep | | Dep | | |
| | | +--------+ +-------+ | | +--------+ +-------+ | | |
| | | | Emp | | Emp | | | | Emp | | Emp | | | |
| | | +--------+ +-------+ | | +--------+ +-------+ | | |
| | +----------------------+ +----------------------+ | |
| +---------------------------------------------------+ |
+-------------------------------------------------------+
フローティング div では実際にそれを行うことはできません。また、絶対配置は機能しますが、固定幅の div は従業員 div のみであるため、含まれるすべての要素の合計幅を取得して、各部門、部門、部門を適切にサイズ設定する必要がありました。および従業員部門。今日、組織図は上から下に広がる傾向があるため、各部門 div で最下位のすべての従業員 div の数を取得するだけでよいという考えがありました。
<xsl:template match="dep">
<!-- Just assuming that dep's, deps's, and emps's have no margin, padding, or border
for the sake of keeping this example simpler -->
<xsl:variable name="emp_count"
select="count(descendant::emp[parent::emps/parent::dep[count(child::deps)=0]])"/>
<xsl:variable name="width" select="$emp_count * $emp_width"/>
<xsl:variable name="mleft" select="$width div 2"/>
<div style="position: absolute; left: 50%; width: {$width}px;
margin-left: -{$mleft}px;">
<xsl:apply-templates/>
</div>
</xsl:template>
一言で言えば、上記は多くのことを省略していますが、私が持っているタイプミスを除けば機能します。しかし!これが問題です。それは、組織がボトムヘビーであるという昔ながらの伝統に従っていることを前提としています。このようなものを出力する必要がある組織ドキュメントを変換するにはどうすればよいですか?
+---------------------------------------------------------------+
| Dep |
| +-----------------------------------------------------------+ |
| | +--------+ +---------+ +--------+ +---------+ +---------+ | |
| | | Emp | | Emp | | Emp | | Emp | | Emp | | |
| | +--------+ +---------+ +--------+ +---------+ +---------+ | |
| +-----------------------------------------------------------+ |
| +---------------------------------------------------+ |
| | +----------------------+ +----------------------+ | |
| | | Dep | | Dep | | |
| | | +--------+ +-------+ | | +--------+ +-------+ | | |
| | | | Emp | | Emp | | | | Emp | | Emp | | | |
| | | +--------+ +-------+ | | +--------+ +-------+ | | |
| | +----------------------+ +----------------------+ | |
| +---------------------------------------------------+ |
+---------------------------------------------------------------+
ああ... 1 週間ずっと頭を悩ませていた問題を解決できるだろうと最初に思っていたものを台無しにするような特別なケースはありません。実際には、そのコーナーケースが出現することはないかもしれません。実際には、div を使用する代わりに、ネストされたテーブルを使用する方が簡単だったかもしれません。
でも、ここにきて、ふと思ったのですが…
このコーナー ケースを念頭に置いて、最上位の部門 div の幅を計算するにはどうすればよいでしょうか。また、このコーナー ケースが階層内の任意の深さで複数回発生する可能性があることも念頭に置いてください。
〜編集〜
この XML ソース ドキュメントを次のように変更します。
<?xml version="1.0" encoding="UTF-8"?>
<dep>
<nm>Dep</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<dep>
<nm>Sub Dep 1</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<dep>
<nm>Sub Dep 1-1</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</dep>
<dep>
<nm>Sub Dep 1-2</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</dep>
</dep>
<dep>
<nm>Sub Dep 2</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<dep>
<nm>Sub Dep 2-1</nm>
<emp>
<nm>Emp</nm>
</emp>
</dep>
<dep>
<nm>Sub Dep 2-2</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</dep>
</dep>
<dep>
<nm>Sub Dep 3</nm>
<emp>
<nm>Emp</nm>
</emp>
</dep>
<dep>
<nm>Sub Dep 4</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<dep>
<nm>Sub Dep 4-1</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<dep>
<nm>Sub Dep 4-1-1</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<dep>
<nm>Sub Dep 4-1-1-1</nm>
<emp>
<nm>Emp</nm>
</emp>
</dep>
<dep>
<nm>Sub Dep 4-1-1-2</nm>
<emp>
<nm>Emp</nm>
</emp>
</dep>
</dep>
</dep>
<dep>
<nm>Sub Dep 4-2</nm>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</dep>
</dep>
</dep>
...この XML 結果ドキュメントに:
<?xml version="1.0" encoding="UTF-8"?>
<deps emps-wide="16">
<dep emps-wide="16">
<nm>Dep</nm>
<emps emps-wide="3">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="16">
<dep emps-wide="5">
<nm>Sub Dep 1</nm>
<emps emps-wide="2">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="5">
<dep emps-wide="3">
<nm>Sub Dep 1-1</nm>
<emps emps-wide="3">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="0"/>
</dep>
<dep emps-wide="2">
<nm>Sub Dep 1-2</nm>
<emps emps-wide="2">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="0"/>
</dep>
</deps>
</dep>
<dep emps-wide="4">
<nm>Sub Dep 2</nm>
<emps emps-wide="4">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="3">
<dep emps-wide="1">
<nm>Sub Dep 2-1</nm>
<emps emps-wide="1">
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="0"/>
</dep>
<dep emps-wide="2">
<nm>Sub Dep 2-2</nm>
<emps emps-wide="2">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="0"/>
</dep>
</deps>
</dep>
<dep emps-wide="1">
<nm>Sub Dep 3</nm>
<emps emps-wide="1">
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="0"/>
</dep>
<dep emps-wide="6">
<nm>Sub Dep 4</nm>
<emps emps-wide="2">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="6">
<dep emps-wide="4">
<nm>Sub Dep 4-1</nm>
<emps emps-wide="3">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="4">
<dep emps-wide="4">
<nm>Sub Dep 4-1-1</nm>
<emps emps-wide="4">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="2">
<dep emps-wide="1">
<nm>Sub Dep 4-1-1-1</nm>
<emps emps-wide="1">
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="0"/>
</dep>
<dep emps-wide="1">
<nm>Sub Dep 4-1-1-2</nm>
<emps emps-wide="1">
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="0"/>
</dep>
</deps>
</dep>
</deps>
</dep>
<dep emps-wide="2">
<nm>Sub Dep 4-2</nm>
<emps emps-wide="2">
<emp>
<nm>Emp</nm>
</emp>
<emp>
<nm>Emp</nm>
</emp>
</emps>
<deps emps-wide="0"/>
</dep>
</deps>
</dep>
</deps>
</dep>
</deps>
完全を期すために、XML 結果ドキュメントのほとんどを生成するために使用した XLST 変換を次に示します。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:call-template name="recurse-deps"/>
</xsl:template>
<xsl:template name="recurse-deps">
<deps emps-wide="">
<xsl:for-each select="dep">
<dep emps-wide="">
<nm><xsl:value-of select="nm"/></nm>
<emps emps-wide="">
<xsl:for-each select="emp">
<emp>
<nm><xsl:value-of select="nm"/></nm>
</emp>
</xsl:for-each>
</emps>
<xsl:call-template name="recurse-deps"/>
</dep>
</xsl:for-each>
</deps>
</xsl:template>
</xsl:stylesheet>
元の質問を一般化したことに注意してください。これが組織図としてどのように表示されるかは気にしません。それは、私が XSLT で解決しようとしていた問題ではありませんでした。
また、XML Result Document を編集しなければならなかったことにも注意してください。なぜなら、私は明らかに、必要なものを作成するための XSLT スタイルシートの書き方をよく知らないからです。そうでなければ、私はここで質問をしません。:)
以下は、XSLT で表現しようとして非常に困難に感じていることと、その変換を実行した後に XML 結果ドキュメントを手動で編集しなければならなかった理由です。
単位が何であれ、すべてのemp要素が 1 単位幅であると仮定します。視覚化できるようにするために、インチと呼びましょう。
すべての emps要素は、その中のemp要素の数と同じ幅にする必要があります。(したがって、3 つのemp要素を含むemps要素の幅は 3 インチになります。)
すべてのdep要素は、そのemps要素またはそのdeps要素のいずれか広い方と同じ幅にする必要があります。(したがって、3 インチ幅のemps要素と 8 インチ幅のdeps要素を持つdep要素は、8 インチ幅になります。5 インチ幅のemps要素と 3 インチ幅のdeps要素を持つdep要素エレメントの幅は 5 インチになります)。
すべての deps要素は、すべてのdep要素の幅の合計と同じ幅にする必要があります。(したがって、 3 インチ幅のdep、5 インチ幅のdep、および別の 5 インチ幅のdepを持つdeps要素は、13 インチ幅になります。)
dep (または部門) には、任意の数のemp要素(または従業員) と任意の数のdep要素 (またはサブ部門) を任意の深さで含めることができます。
したがって、私が XSLT で解決したい問題は、一般的で再帰的に構造化された XML ソース ドキュメントを XML 結果ドキュメントに変換する方法であり、各要素 (またはほとんどの要素) に何らかの計算値が付加されている必要があります。その子の同じまたは同様の計算値に依存します...など...など...「リーフノード」になる可能性のあるものまでずっと。
簡単な編集: もっと考えてみると、この種の問題の同様の例は、「ファイル システム」XML ソース ドキュメントを XML 結果ドキュメントに変換することです。その中のファイルの総数とその「サブフォルダー」、およびそれらの「サブフォルダー」など。
これを行う方法を学ぶ上での助けは...いいえ、特にそれを行うための慣用的な方法が複数ある場合は、深く感謝します。