XSLT1.0でこれを行う1つの方法は、 person-listの下の非pid要素を最初の最も前のpid要素でグループ化するキーを定義することです。
<xsl:key
name="fields"
match="person-list/*[not(self::pid)]"
use="generate-id(preceding-sibling::pid[1])" />
次に、person-list要素には、 pid要素のみを選択します。
<xsl:apply-templates select="pid" />
そして、pidに一致するテンプレート内で、 person要素を作成し、キーを使用して他の要素を出力します。
<xsl:apply-templates select="key('fields', generate-id())" />
これが完全なXSLTです
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="fields" match="person-list/*[not(self::pid)]" use="generate-id(preceding-sibling::pid[1])" />
<xsl:template match="person-list">
<person-list>
<xsl:apply-templates select="pid" />
</person-list>
</xsl:template>
<xsl:template match="pid">
<person>
<xsl:copy-of select="." />
<xsl:apply-templates select="key('fields', generate-id())" />
</person>
</xsl:template>
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
サンプルXMLに適用すると、次のように出力されます。
<person-list>
<person>
<pid>100</pid>
<pname>Tom Jones</pname>
<pdescription>Some Text</pdescription>
</person>
<person>
<pid>101</pid>
<pname>John Thomas</pname>
<pdescription></pdescription>
</person>
</person-list>
このアプローチでは、XSLTを修正することなく、各人の入力ドキュメントにさらにフィールドを追加できることに注意してください。
また、既存の要素をコピーするための「ID変換」の使用にも注意してください。