質問
次のような階層 XML を変換するための汎用的な方法が必要です。
<element1 A="AValue" B="BValue">
<element2 C="DValue" D="CValue">
<element3 E="EValue1" F="FValue1"/>
<element3 E="EValue2" F="FValue2"/>
</element2>
...
</element1>
フラット化された XML (html) に変換され、途中で選択された属性が取得され、列ヘッダーとなる属性にさまざまなラベルが提供されます。
<table>
<tr>
<th>A_Label</th>
<th>D_Label</th>
<th>E_Label</th>
<th>F_Label</th>
</tr>
<tr>
<td>AValue</td>
<td>DValue</td>
<td>EValue1</td>
<td>FValue1</td>
</tr>
<tr>
<td>AValue</td>
<td>DValue</td>
<td>EValue2</td>
<td>FValue2</td>
</tr>
<table>
属性のラベル付けが変更されているため、一般的な解決策はありませんが、私の言いたいことは理解していただけたと思います。XSLT/XPATH に関するすべての作業を開始したばかりなので、時間内に解決する予定ですが、手がかりがあれば役立つでしょう。
解決
あなたがやろうとしていることを100%確信しているわけではありませんが、element1、element2、element3が一貫してネストされている場合、この解決策は機能する可能性があります。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<table>
<xsl:apply-templates select="//element3"></xsl:apply-templates>
</table>
</xsl:template>
<xsl:template match="element3">
<tr>
<td><xsl:value-of select="../../@A"/></td>
<td><xsl:value-of select="../../@B"/></td>
<td><xsl:value-of select="../@C"/></td>
<td><xsl:value-of select="../@D"/></td>
<td><xsl:value-of select="@E"/></td>
<td><xsl:value-of select="@F"/></td>
</tr>
<xsl:apply-templates select="*"></xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
他のヒント
同様の XSLT が必要でしたが、深さは不明でした。その方法を次に示します。
まず、結果の HTML table/def リストのラッパーを追加し、テンプレート mode="puke" を呼び出して XML ツリーをフラット化します。
<xsl:element name="div">
<xsl:attribute name="class" select="puke" />
<xsl:apply-templates select="$notice" mode="puke" />
</xsl:element>
ここでは、各ノードを照合してそのコンテンツを表示します (例:text()) とその属性。これを再帰的に実行します。ソース ツリーが複雑なツリーであり、 としてフラット化できないため、dl/dt/dd を使用しました。
<!-- @description:
Display all field from the notice so the customer can tell what he want
-->
<xsl:template match="node()" mode="puke">
<xsl:message>
puking : <xsl:value-of select="local-name( . )" />
</xsl:message>
<xsl:element name="dl">
<xsl:element name="dt">
<xsl:attribute name="class">tagName</xsl:attribute>
<xsl:value-of select="local-name( . )" />
</xsl:element>
<xsl:element name="dd">
<xsl:attribute name="class">tagText</xsl:attribute>
<xsl:value-of select="text()" /></xsl:element>
<xsl:element name="dl">
<xsl:attribute name="class">attr</xsl:attribute>
<!-- display attribute -->
<xsl:apply-templates select="@*" />
</xsl:element>
</xsl:element>
<!-- recursive call on node() -->
<xsl:apply-templates select="./*" mode="puke" />
</xsl:template>
指定されたノードの属性を照合して表示します。
CSS は、結果の HTML をフォーマットするために使用されます。
<style>
.puke {
background-color: #BDD6DE;
clear: both;
}
.tagName, .attrName {
float: left;
}
.tagText, .attrText {
clear: right;
}
</style>
Oracle データベースから読み取る Pro*C プログラムがすでにあります。このプログラムは Perl スクリプトを呼び出し、Java を実行して前述のデータベースから XML 形式でデータを抽出し、バッチ ファイルを呼び出して vbscript を実行し、そのファイルを他のファイルに FTP 送信します。サーバ。私は本当に Fortran で何かを期待していました。
元の質問を明確にする必要があります。
- 元の質問の BValue と CValue はどうなりますか?それらがフラット化された構造の一部であってはいけない理由はありますか?
- XML ドキュメント内のすべての要素には 2 つの属性がありますか、それともこれは完全に任意ですか?
- 要素は 3 種類のみで、例に示すように常に入れ子になっていますか?
- element1 自体を繰り返すことができますか、それともこれはドキュメントのルート要素ですか?
XSLT では、非常に汎用的なトランスフォーマーを作成できますが、既知の制限を考慮できる場合は、ドキュメントを変換するためのスタイルシートを作成する方がはるかに簡単であることがよくあります。
構造化 XML をフラット化するために、以下のテンプレートの拡張バージョンを使用しました。警告:元のバージョンにはケース固有のコードがいくつかありました (実際には XML を CSV に変換していました)。それを取り除いただけで、このバージョンはテストしませんでした。
基本的な動作方法は明らかです。ノードの子を持たないすべてのものを出力し、それ以外の場合は、子を持つノード() でテンプレートを再帰的に呼び出します。現状では属性とコメントが正しく処理されていないと思いますが、修正するのは難しくないはずです。
<?xml version="1.0" encoding="UTF-8"?>
<!-- XSL template to flatten structured XML, before converting to CSV. -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*" />
<xsl:template match="/">
<xsl:apply-templates select="//yourElementsToFlatten"/>
</xsl:template>
<xsl:template match="//yourElementsToFlatten">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:choose>
<!-- If the element has multiple childs, call this template
on its children to flatten it-->
<xsl:when test="count(child::*) > 0">
<xsl:apply-templates select="@*|node()"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:value-of select="text()" />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>