@LarsHがすでに指摘しているように、期待される出力XMLを表示しないことで、本当に必要なものを推測する必要があります。そうは言っても、これがXSLT1.0ソリューションでの私の試みです。
このXSLTの場合:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key
name="PropertiesByAttributeNameVal"
match="Properties"
use="concat(name(@*[1]), '+', @*[1])" />
<xsl:key
name="ItemsByAttributeNameVal"
match="Items"
use="concat(name(@*[1]), '+', @*[1])" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Rootnode">
<Rootnode>
<xsl:apply-templates
select="Properties[
generate-id() =
generate-id(key(
'PropertiesByAttributeNameVal',
concat(name(@*[1]), '+', @*[1]))[1])]">
<xsl:with-param name="pKeyName"
select="'PropertiesByAttributeNameVal'" />
<xsl:sort select="concat(name(@*[1]), '+', @*[1])" />
</xsl:apply-templates>
<xsl:apply-templates
select="Items[
generate-id() =
generate-id(key(
'ItemsByAttributeNameVal',
concat(name(@*[1]), '+', @*[1]))[1])]">
<xsl:with-param name="pKeyName"
select="'ItemsByAttributeNameVal'" />
<xsl:sort select="concat(name(@*[1]), '+', @*[1])" />
</xsl:apply-templates>
</Rootnode>
</xsl:template>
<xsl:template match="Properties|Items">
<xsl:param name="pKeyName" />
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates
select="key($pKeyName, concat(name(@*[1]), '+', @*[1]))/*">
<xsl:sort select="name()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
...提供されたXMLに対する実行:
<Rootnode>
<Properties Attribute="xxx">
<Type>1</Type>
<Size>10</Size>
</Properties>
<Other>
<blah>h</blah>
</Other>
<Other2>
<blah>h</blah>
</Other2>
<Properties Attribute="xxx">
<xType>5</xType>
<xSize>10</xSize>
</Properties>
<Items>
<Item4>8</Item4>
</Items>
<Items>
<Item6>8</Item6>
</Items>
<Properties Attribute="xxx">
<zType>1</zType>
<zSize>10</zSize>
</Properties>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>
...私が推測するのは、正しい出力XMLが生成されることです。
<?xml version="1.0"?>
<Rootnode>
<Properties Attribute="xxx">
<Size>10</Size>
<Type>1</Type>
<xSize>10</xSize>
<xType>5</xType>
<zSize>10</zSize>
<zType>1</zType>
</Properties>
<Items>
<Item4>8</Item4>
<Item6>8</Item6>
</Items>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>
この同じXSLTがわずかに変更されたXMLドキュメント(より多くのグループ化などがある)に対して実行される場合は、次の点に注意してください。
<?xml version="1.0" encoding="utf-8"?>
<Rootnode>
<Properties Attribute="xxx">
<Type>1</Type>
<Size>10</Size>
</Properties>
<Other>
<blah>h</blah>
</Other>
<Other2>
<blah>h</blah>
</Other2>
<Properties Attribute="yyy">
<xType>5</xType>
<xSize>10</xSize>
</Properties>
<Items>
<Item4>8</Item4>
</Items>
<Items place="US">
<Item9>8</Item9>
</Items>
<Items>
<Item1>8</Item1>
</Items>
<Properties Attribute2="xxx">
<zType>1</zType>
<zSize>10</zSize>
</Properties>
<Properties Attribute="xxx">
<elephantType>5</elephantType>
<elephantSize>15</elephantSize>
</Properties>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>
...繰り返しますが、正しい答えが生成されると私は思います:
<?xml version="1.0"?>
<Rootnode>
<Properties Attribute="xxx">
<Size>10</Size>
<Type>1</Type>
<elephantSize>15</elephantSize>
<elephantType>5</elephantType>
</Properties>
<Properties Attribute="yyy">
<xSize>10</xSize>
<xType>5</xType>
</Properties>
<Properties Attribute2="xxx">
<zSize>10</zSize>
<zType>1</zType>
</Properties>
<Items>
<Item1>8</Item1>
<Item4>8</Item4>
</Items>
<Items place="UK">
<Item1>8</Item1>
</Items>
<Items place="US">
<Item9>8</Item9>
</Items>
</Rootnode>
仮定:
- それぞれ
<Properties>
の<Items>
要素には1つの属性しかなく、それがグループ化の決定要因になるはずだと思います。
- 上記が当てはまらない場合は、少なくとも、その要素の最初の属性はグループ化の限定詞である必要があると思います。
説明:
これはXSLT1.0ソリューションでMuenchian Grouping
あるため、一意のセレクターの下でノードと属性をグループ化する日の順序です。したがって、2つのキーを定義します。1つは<Properties>
要素用、もう1つは<Items>
要素用です。
最初のテンプレートはIdentity Transform
-その仕事は、すべてのノードと属性をソースドキュメントから結果ドキュメントにそのまま出力することです。
2番目のテンプレートは<Rootnode>
要素と一致します。それぞれのキーに最初に表示される要素<Properties>
と要素にのみテンプレートを適用するように指示されています。<Items>
これには、(最初の属性の名前と値に基づいて)一意の要素のみを処理するという意図された効果があります。
要素を指定する<xsl:apply-templates>
と、どちらの場合も、同じ属性名と値の組み合わせで結果を並べ替えるように指示されることに注意してください。
<xsl:apply-templates>
各要素には(を介して)パラメータが与えられていることに注意してください<xsl:with-param>
。ご覧のとおり、要素<Properties>
と<Items>
要素の両方を処理するコードはほぼ同じです。唯一の違いは、結果を取得するためのキーです。このため、そのロジックを3番目のテンプレートに統合し、このパラメーターを介して変動性を考慮することにしました。
3番目のテンプレートは<Properties>
と<Items>
要素の両方に一致します。それぞれについて、元のノードがコピーされます(その属性も同様です)。最後に、テンプレートがこの要素のすべての子要素に適用されます([今回は、子要素自体の名前に基づいて]適切な並べ替えが行われます)。