xml→xmlを行うxsltの記述方法で質問があります。
元のxmlの例を下に示します。
<?xml version="1.0" encoding="Shift_JIS" ?>
<root>
<A1>
<B1>
<DATA1>aaa</DATA1>
<DATA2>bbb</DATA2>
</B1>
</A1>
<A2>
<DATA3>ccc</DATA3>
<DATA4>ddd</DATA4>
<B2>
<DATA5>eee</DATA5>
<C1>
<DATA6>fff</DATA6>
</C1>
<DATA7>ggg</DATA7>
</B2>
</A2>
<DATA8>hhh</DATA8>
</root>
(実際はDATA1,DATA2のような規則的な要素名ではありません)
変換後のxmlとしては
<root>
<DATA1>aaa</DATA1>
<DATA2>bbb</DATA2>
・
・
・
<DATA8>hhh</DATA8>
</root>
のように、値を持っている要素だけを、ルートノードの下に記述したものが欲しいのです。
作った物としては、
<xsl:template match="DATA1" >
<xsl:copy>
<xsl:value-of select="." />
</xsl:copy>
</xsl:template>
このようなtemplateをDATA1-8まで記述するものです。
何か簡潔な記述方法はないでしょうか?
よろしくお願いいたします。
No.1
- 回答日時:
=================================Q4519133-1.xml(入力)======================
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<A1>
<B1>
<DATA1>aaa</DATA1>
<DATA2>bbb</DATA2>
</B1>
</A1>
<!-- このA2要素自体は取得されない-->
<A2>xxx <DATA3>ccc</DATA3>
<DATA4>ddd</DATA4>
<B2>
<DATA5>eee</DATA5>
<C1>
<DATA6>fff</DATA6>
</C1>
<DATA7>gg<!-- ppp -->g</DATA7> <!--DATA7は取得される-->
</B2>
</A2>
<DATA8>hhh</DATA8>
</root>
=================================Q4519133-1.xsl(変換)======================
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:element name="{local-name(.)}" namespace="{namespace-uri(.)}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:choose>
<!--
質問文中に指示が無かったので、
1.最下層にある「空要素」は取得しません。(空の要素自体出力されない。)
2.コメントノード・処理命令・CDATAマーク区間は階層としない
3.コードが示すとおり,混在内容に含まれる,テキストノードのある要素は取得しません。
4.ただし,テキストノード以外の内容がコメント・処理命令・CDATAマーク区間のみである
要素については取得した。嫌ならpreceding-sibling::node()とでもすれば良い。
5.取得した要素についてはコピーを行なった。テキストノードだけが欲しいなどの場合は
xsl:elementやxsl:value-of selectで地道に書く必要がある。
-->
<!-- 後半の条件がないとDATA7が二つ取得されるハメになる-->
<xsl:when test="count(preceding-sibling::*|following-sibling::*) = 0 and count(preceding-sibling::text()) = 0">
<xsl:copy-of select="parent::*" />
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
=================================Q4519133-2.xml(結果)======================
<?xml version="1.0" encoding="utf-8"?>
<root>
<DATA1>aaa</DATA1>
<DATA2>bbb</DATA2>
<DATA3>ccc</DATA3>
<DATA4>ddd</DATA4>
<DATA5>eee</DATA5>
<DATA6>fff</DATA6>
<DATA7>gg<!-- ppp -->g</DATA7>
<DATA8>hhh</DATA8>
</root>
==========================
あんまりエレガントじゃないな
テキストノードからやった方が楽かと思ったら混在内容考えるとそうでもなかったorz
No.3ベストアンサー
- 回答日時:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/*">
<xsl:element name="{local-name(.)}" namespace="{namespace-uri(.)}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="count(*) = 0">
<xsl:copy-of select="." />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="*" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
このほうが圧倒的に簡単だね。(ただし,空要素はとってくる方針に変更)
この回答への補足
himajin100000様
適用したところ、希望通りの出力結果となりました。
このスタイルシートの内容について確認させてください。
1.
<xsl:template match="/*">
<xsl:element name="{local-name(.)}" namespace="{namespace-uri(.)}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
上記の部分で、xmlのルートノード以下全要素に対して、出力要素を作成しに行くのは分かるのですが、nameとnamespaceに何をしているのかがイマイチ掴めません。
nameに要素名をコピー、namespaceには要素の名前空間URI(?)をコピー?しているのでしょうか。
そもそもこのnamespaceは何故必要になるのでしょうか。
2.<xsl:template match="*">
<xsl:choose>
<xsl:when test="count(*) = 0">
<xsl:copy-of select="." />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="*" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
子の要素を持たない要素を判定するのが
<xsl:when test="count(*) = 0">
この部分。この条件を通ればコピーして、要素を出力。
<xsl:otherwise>
<xsl:apply-templates select="*" />
</xsl:otherwise>
の所は繰り返し処理を短くするために、selectで指定していると考えてよいのでしょうか。
以上2点の追加質問申し訳ございません。
またよろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) pandasでまとめてインデックスを削除するにはどうすればいいですか? たとえば、以下のプログラムで 1 2022/07/31 23:09
- UNIX・Linux Linuxについて質問です。 以下のような設定をしたMakefileを作成するにはどう記述すればよい 1 2023/02/03 20:10
- その他(プログラミング・Web制作) google formsを使ったタスク依頼フォーム作成におけるご相談 1 2023/06/22 15:55
- その他(プログラミング・Web制作) Fortranでの出力ファイル 2 2023/03/21 21:25
- Visual Basic(VBA) 複数シート一括作成後に、特定範囲の数式は値で貼り付けしたい 3 2022/10/07 11:18
- JavaScript EasyUIのSubGrid(jquery)におけるObjectに入れた連想配列について 1 2022/05/02 11:21
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- MySQL MYSQL エラー 2 2022/10/18 11:37
- Java JaneStyleのスレッドが見れなくなった 1 2023/06/10 08:02
- その他(プログラミング・Web制作) pythonでDBのカラム名で取得したオブジェクトの値を表示したい 1 2022/05/13 03:41
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
XSLで、XMLの空タグを制御したい。
-
XMLで要素が記述された順番に意...
-
CPUの考え方を教えてください ...
-
東芝のDynabookなのですがアン...
-
SNMP リンクダウンとノードダ...
-
Excel-VBAでXMLの複数ノードの...
-
XPathで途中に名前空間が設定さ...
-
バッチファイルでテキストファ...
-
C#で使用中のファイルに別のフ...
-
昔Winnyってありましたけど、あ...
-
c言語 ノードの連結
-
VBAでXMLを出力するプログラム...
-
ルート要素ノードが2個ある場合?
-
DOSコマンドラインからxmlファ...
-
UTF-8でエンコーディングとはど...
-
同じタグ名の項目取得
-
コンテキストメニュークリック...
-
XMLで特殊文字を扱うにはどうし...
-
複数のマックPCによる数値計算...
-
プログラミングC言語について次...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
XMLのHTMLへの変換 (初心者)
-
XSLで、XMLの空タグを制御したい。
-
タグの有無の判定
-
htmlに変換されない
-
スタイルシートを使用したXM...
-
xslでの最小値、最大値の取得
-
ノードの並び替え
-
VBAからxml・スタイルシートを...
-
XSL内でJavaScriptを記述し、Ja...
-
xmlのテキストにリンクを張りた...
-
重複するものを消したい
-
<xsl:key>とtopreceding-siblin...
-
XSL中の改行、タブを無効にした...
-
スタイルシートについて
-
XMLをXSLを使いHTMLに変換した...
-
XSLTで直下のテキストのみ取得...
-
XSLTにてタグ名を取得する方法
-
xsl:variable の使用方法
-
東芝のDynabookなのですがアン...
-
CPUの考え方を教えてください ...
おすすめ情報