- ベストアンサー
スマートなxsltの記述方法
- XMLからXMLへの変換でスマートなXSLTの記述方法について質問があります。
- 要素名が規則的でないXMLを値を持つ要素のみに変換する方法を教えてください。
- DATA1からDATA8までの要素を抽出するために、簡潔な記述方法はありますか?
- みんなの回答 (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> このほうが圧倒的に簡単だね。(ただし,空要素はとってくる方針に変更)
その他の回答 (2)
- himajin100000
- ベストアンサー率54% (1660/3060)
テキストノードから考えてたの,やっぱり考え直すかも。(コメントノードと処理命令ノードのみからなるノードのこと忘れてる)
- himajin100000
- ベストアンサー率54% (1660/3060)
=================================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
お礼
書き込みありがとうございます! 明日早速教えていただいた2通りのやり方を試して、勉強させていただきます。
補足
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点の追加質問申し訳ございません。 またよろしくお願いいたします。