• ベストアンサー
  • すぐに回答を!

スマートなxsltの記述方法

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まで記述するものです。 何か簡潔な記述方法はないでしょうか? よろしくお願いいたします。

共感・応援の気持ちを伝えよう!

  • XML
  • 回答数3
  • 閲覧数196
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答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点の追加質問申し訳ございません。 またよろしくお願いいたします。

その他の回答 (2)

  • 回答No.2

テキストノードから考えてたの,やっぱり考え直すかも。(コメントノードと処理命令ノードのみからなるノードのこと忘れてる)

共感・感謝の気持ちを伝えよう!

  • 回答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

共感・感謝の気持ちを伝えよう!

質問者からのお礼

書き込みありがとうございます! 明日早速教えていただいた2通りのやり方を試して、勉強させていただきます。

関連するQ&A

  • XSLTについて

    入力となるXMLの要素Aに属性が複数存在した場合に、ある属性以外のすべての属性を要素Bに付与して出力したいのですがどのようなXSLTで記述すればいいのでしょうか? 入力例) <sample> <要素 aa="1" bb="2" cc="3">AAAAAAA</要素> </sample> 出力例) <sample> <youso bb="2">AAAAA</youso> </sample> XSLT) <?xml version="1.0" encoding="Shift_JIS"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/ 1999/XSL/Transform" version="1.0"> <xsl:template match="/">   <sample> <xsl:apply-templates/> </sample> </xsl:template> <xsl:template match="要素"> <xsl:copy> <!-- <xsl:copy-of select="@*"/> -->☆ </xsl:copy> </xsl:template> </xsl:stylesheet>

    • 締切済み
    • XML
  • XSLTの記述方法

    お世話になります。 XML+XSLTで開発しております。 XSLTの記述方法でjavascriptの引数にXMLデータを挿入する記述は どうすればよいのでしょうか? すごい初歩的な質問かもしれませんが ご教授よろしくお願いいたします。 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <table> <tr> <td > <a href="#" onClick="hogehoge('pram')">hogehoge rink </a> </td> </tr> </table> </xsl:template> </xsl:stylesheet> ↓↓↓↓↓↓こんな感じにしたい↓↓↓↓↓↓ <a href="#" onClick="hogehoge('<xsl:value-of select="$prm_test"/>')">りんく</a>

    • ベストアンサー
    • XML
  • XSLT

    いつもお世話になっております。 次のXSLTの結果がどうしてそうなるのかわからないので教えてください。 解説には、「処理は必ずルートノードのテンプレートから始まります」と書いてあるんですが、できましたら、その辺もからめて、どういう処理の流れになるのか、カレントノードがどう移動していくのか、教えていただけると助かります。 (XML) <?xml version="1.0" encoding="Shift_JIS"?> <Conference Situation="Reserved" Equipment="Projector">  <Room>会議室</Room>  <User>山田太郎   <Date>2008/05/08</Date>   <Time>10:00-12:00</Time>  </User>  <Number>4名</Number> </Conference> (XSLT) <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  <xsl:output method="text" />  <xsl:template match="/Conference">   <xsl:value-of select="Number" />  </xsl:template>  <xsl:template match="Conference/User">   <xsl:value-of select="Date" />  </xsl:template>  <xsl:template match="/">   <xsl:value-of select="Conference/Room" />  </xsl:template> </xsl:stylesheet> (結果) 会議室

    • ベストアンサー
    • XML
  • javascriptからxsltに値を渡したい

    お世話になります。 下記のサイトを参考に http://webcache.googleusercontent.com/search?q=cache:587mPIaRXcwJ:www.tagindex.com/kakolog/q4bbs/1701/2037.html+xsltProc.setParameter&cd=5&hl=ja&ct=clnk&gl=jp&lr=lang_ja http://webcache.googleusercontent.com/search?q=cache:qLCKa_Rxc58J:domes.lingua.heliohost.org/dom/intro-misc2.html+xsltProc.setParameter&cd=2&hl=ja&ct=clnk&gl=jp&lr=lang_ja http://webcache.googleusercontent.com/search?q=cache:SJR9ZdyaGNUJ:taugus.web.fc2.com/WEB/XML/xml.html+javascript%E3%81%8B%E3%82%89xslt%E3%81%AB%E5%80%A4%E3%82%92%E6%B8%A1%E3%81%97%E3%81%9F%E3%81%84&cd=4&hl=ja&ct=clnk&gl=jp javascriptからxsltに値を渡したいと考え、下記のように設定してみているのですが、思うようにxsltファイルで参照出来ず、途方に暮れております。 どなた様か解決法などご教授願えませんでしょうか。お願い致します。 ※環境は、FireFox3.5を使っておりまして、現状、FireFoxのみで動作すれば良いと考えてます。 --test-1.html---- <html><head> <meta content="text/html; charset=utf8" http-equiv="content-type"> <title>JS+xslt</title> <script type="text/javascript"> function tramsformlists(xmlFile, xslFile, resultNodeID, Num){//chTag=inputのthis.value // alert("resultNodeIDは" + resultNodeID + "です。"); var xml, xslt, newDoc; var doc = document; var impl = doc.implementation; // XML ドキュメントの読み込み var xml = impl.createDocument("", "", null); xml.async = false; xml.load(xmlFile); // XSL ドキュメントの読み込み var xslt = impl.createDocument("", "", null); xslt.async = false; xslt.load(xslFile); // XSLT プロセッサを作成 var xsltp = new XSLTProcessor(); xsltp.importStylesheet(xslt); // 下記2つのどちらかの方法で取得したいと思ってますが、xslt側で、どちらの方法でも参照できないです xsltp.setParameter ('', "param.num", param.value); xsltp.setParameter ('', "Num", Num); // XSLT 実行(戻り値は文書断片ノード) var df = xsltp.transformToFragment(xml, doc); // 結果を付加 // var t3 = doc.getElementById("LorRorC"); // t4=t3.options[t3.selectedIndex].value; // alert("resultNodeIDは" + t4 + "です。"); var t1 = doc.getElementById("Div"+resultNodeID); t1.innerHTML = ""; t1.appendChild(doc.importNode(df, true)); var t2 = doc.forms["msg_form"].elements["Textarea" + resultNodeID]; t2.value = (new XMLSerializer).serializeToString(df);//DOM ノードを XML データに書き出す } </script> </head><body> <form name="msg_form"> <ul> <li> <input type="button" value="Menu" onclick="tramsformlists('test0.xml','test0.xsl','Test','10')"><br> <select name="num"> <option value="10" selected="selected">10</option> </select> <div id="DivTest"></div> <textarea cols="50" rows="10" id="TextareaTest">あああああああ</textarea> </li> </ul> </form> </body></html> ---- --test0.xml--- <?xml version="1.0" encoding="utf-8"?> <root> <nolink_logo> </nolink_logo> </root> ---- --test0.xsl--- <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="utf-8"/> <xsl:template match="root"> <xsl:apply-templates select="nolink_logo"/> </xsl:template> <xsl:template match="nolink_logo"> <xsl:call-template name="Test" /> </xsl:template> <xsl:template name="Test"> <xsl:variable name="menu" select="document('test1.xml')/root"/> <xsl:param name="param.num">0</xsl:param> <xsl:param name="Num">0</xsl:param> <div id="{$param.num} {$Num}">画像を表示 <xsl:for-each select="$menu"> <xsl:element name="a"> <xsl:attribute name="href"> <xsl:value-of select="url[1]"/> </xsl:attribute> <xsl:attribute name="target">_blank</xsl:attribute> <xsl:element name="img"> <xsl:attribute name="src"> <xsl:value-of select="img[1]"/> </xsl:attribute> </xsl:element> </xsl:element> </xsl:for-each> </div> </xsl:template> </xsl:stylesheet> ---- --test1.xml-- <?xml version="1.0" encoding="utf-8"?> <root> <img>http://domain/image2.gif</img> <url>http://domain/test.html</url> </root> ---- 大変恐縮ですが、どなた様かご教授頂けませんでしょうか 宜しく願い致します。

  • DTDを記述する意味

    DTDを使ってXMLの形式を厳密に定義する方法があると聞いて試してみたのですが、記述した形式を破っても何も起きません。たとえば以下のように <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ELEMENT root (a, b, c+)> ]> <root> <b>BBB</b> <a>AAA</a> </root> と書いた場合、「A,B,Cという要素をこの順番で配置せよ」という命令と「Cという要素を1つ以上配置せよ」という2つの命令を無視していますが、何かしらのエラーを返すといった動作は全くありません。HTML(XHTML)みたいな感じです(テキトーにコーディングしてもエラーを返さない点)。XMLのDTDはそれを守らないとエラーを返すような動作はしないのでしょうか?それではDTDの存在意義が分からなくなってしまいますが・・・

    • 締切済み
    • XML
  • Firefox・GoogleChromeでのxslt読み込み

    Firefox・GoogleChromeでのxslt読み込み 現在、xml + xsltでhtmlを生成する試験をしているのですが、 Firefox・GoogleChromeで意図通りの結果にならず悩んでおります。 ソースは下記の通りなのですが、何かアドバイスをいただけたら助かります。 test.xmlとtest.xslを下記のようなフォルダ構成で配置する。 【フォルダ構成】 project |-xml | |-test.xml |-xsl |-test.xsl 【ソース】 test.xml <?xml version = "1.0" encoding = "utf-8"?> <?xml-stylesheet type = "text/xsl" href = "../xsl/test.xsl"?> <tests name = "test"> <test> <tag>aaa</tag> </test> <test> <tag>bbb</tag> </test> <test> <tag>ccc</tag> </test> </tests> test.xsl <?xml version = "1.0" encoding = "utf-8" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method = "html" encoding = "utf-8" doctype-system = "string" media-type = "text/xml" /> <xsl:template match="/"> <html lang = "ja-JP"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <title><xsl:value-of select = "tests/@name" /></title> </head> <body> <xsl:apply-templates /> </body> </html> </xsl:template> <xsl:template match = "test"> <div> <xsl:value-of select = "tag" /> </div> </xsl:template> </xsl:stylesheet> 【結果】 ・IE・Safari・Opera -> ちゃんと表示してくれる ・Firefox(Ver3.5.3) -> NG   ->・ページタイトル反映されない    ・tagの中身("aaa"・"bbb"・"ccc")が一行に表示されてしまう ・Google Chrome(Ver5.0.342.8 beta) -> NG   ->・何も表示されず、画面真っ白    ・デベロッパーツールでは、"Unsafe attempt to load URL・・・"とエラーが出ている 【備考】 ・『Mozilla で扱えるMIMEタイプは、IEより厳密』みたいな記述を見つけたので、 test.xslの3行目に呪文みたいなのを見よう見真似で書いてみたのですが、 効果なし。というか、この記述があってるのかも分からない。。。 ・Firefoxの場合、同じフォルダにtest.xmlとtest.xslを配置すると ちゃんと表示してくれる。 長々となってしまいましたが、よろしくお願いします。

    • 締切済み
    • XML
  • ルート要素ノードが2個ある場合?

    xmlからxmlへの変換時に出るエラーについての質問です。 元データとなるxmlが下のような構造をしています。 ルート要素の要素ノードが2つあるものです。 <A1>   <B1>aaa</B1>   <B2>     <C1>bbb</C1>   </B2> </A1> <A2>ccc</A2> これをxsltで違う形のxmlに変換するのですが、変換中にエラーが出てしまいます。 (使用しているのはApache xalanです) 現在は元データに、<root>ノードを最上位に加えることにより、変換しているのですが、他の方法で対処できないでしょうか? よろしくお願いいたします。

    • ベストアンサー
    • XML
  • xsltを利用して変換後改行が入る

    MSXMLを利用して、XMLをHTMLへ変換しているのですが、変換後、改行が入ってしまいます。 どうすれば改行を取ることができるでしょうか? 【xslt】 <xsl:template match="ruby"><xsl:copy-of select="self::node()" /></xsl:template> 【XML】 <ruby><rb>○</rb><rp>〔</rp><rt>××</rt><rp>〕</rp></ruby> 【結果(HTML)】 <ruby xmlns=""> <rb>○</rb> <rp>〔</rp> <rt>××</rt> <rp>〕</rp>

    • 締切済み
    • XML
  • XMLの実体参照とXSLT

    次のようなXMLファイルをXSLTで処理したいのですが、&baseの部分がうまく表示できません。 どのようにしたら表示できるでしょうか? ■a.xml <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="a.xsl"?> <!DOCTYPE test [ <!ELEMENT name (#PCDATA)> <!ENTITY base SYSTEM "base.xml"> ]> <test> <name>abc</name> &base; </test> ■base.xml <?xml version="1.0" encoding="UTF-8"?> <base>base</base> ■a.xsl <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" encoding="UTF-8" /> <xsl:template match="/"> <xsl:apply-templates select="test" /> <xsl:apply-templates select="base" /> </xsl:template> <xsl:template match="test"> name:<xsl:value-of select="name" /> </xsl:template> <xsl:template match="base"> base:<xsl:value-of select="base" /> </xsl:template> </xsl:stylesheet> □結果 name:abc ※base.xmlの内容を表示できない

    • ベストアンサー
    • XML
  • csv作成エラー

    CSVファイルを作ろうとcsvフォルダを作り、xmlファイル・xslファイルを入れました。 C:\csv\aaa.xml C:\csv\bbb.xsl コマンドプロンプトで C:\csv>java org..apache.xalan.xslt.Process -in aaa.xml -xsl bbb.xsl -out ddd.csv と入力したら、 file:/C:/csv/bbb.xsl;行番号1;列番号-1;XSLTエラー(javax..xml.transform.TransformerConfigurationException):javax..xml.transform.TransformerException: org.xml.sax.SAXParseException: ドキュメントのルート要素がありません。 と表示されてうまくいきません。 xslファイルの1行目には、<?xml version="1.0" encoding="utf-8"?>と記載されています。 教えていただけたらうれしいです。

    • ベストアンサー
    • XML