C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: XMLをCSVに変換する XSLT


(過去ログ 71 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■41597 / inTopicNo.1)  XMLをCSVに変換する XSLT
  
□投稿者/ Travian (1回)-(2009/09/25(Fri) 12:07:50)

分類:[XML] 

■data.xml
<?xml version="1.0" standalone="yes"?>
<DataSet1 xmlns="http://tempuri.org/DataSet1.xsd">
<ういうい>
<No.>1</No.>
<品番>XBF222</品番>
<上限値>52.0</上限値>
<下限値>48.0</下限値>
</ういうい>
<ういうい>
<No.>2</No.>
<品番>XBF222</品番>
<上限値>42.0</上限値>
<下限値>48.0</下限値>
</ういうい>
<ういうい>
<No.>3</No.>
<品番 />
</ういうい>
</DataSet1>

■xmltocsv.xslt
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:text>No.,品番,上限値,下限値
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/DataSet1/ういうい">
<xsl:for-each select="*">
<xsl:value-of select="text()"/>
<xsl:if test="position()!=last()">","</xsl:if>
<xsl:if test="position()=last()">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>


上記
「data.xml」を「xmltocsv.xslt」使って
カンマ区切りのCSVに吐き出したいのですが
出力結果は以下のようなありさまです。

■data.csv
No.,品番,上限値,下限値
1XBF22252.048.02TCF10852.049.03

■data.csv(希望)
No.,品番,上限値,下限値
1,XBF222,52.0,48.0
2,TCF108,52.0,49.0
3

どこが間違っているのでしょう。。。
カンマも改行も無視されているような感じです。
<xsl:template match="/DataSet1/ういうい">
このあたりのマッチ指定に問題あるのでしょうか?
完全にスルーされている気がしてます。
アドバイスお願いします。
引用返信 編集キー/
■41601 / inTopicNo.2)  Re[1]: XMLをCSVに変換する XSLT
□投稿者/ Hongliang (471回)-(2009/09/25(Fri) 13:28:25)
template にマッチしてませんね。
data.xml において、DataSet1 及びその子要素は xmlns 指定によって http://tempuri.org/DataSet1.xsd という名前空間に属しています。
xsl:template 要素で match がグローバルな名前空間の DataSet1 要素やら ういうい 要素を指しているので、他の名前空間内にある DataSet1 等は見つけられません。
xsl:stylesheet ルート要素で xmlns:ds="http://tempuri.org/DataSet1.xsd" などとして名前空間を宣言し、/ds:DataSet1/ds:ういうい などという風にマッチさせるようにしましょう。

というか、正直 xslt よりスクリプトなり使って書き出した方が楽だと思うなぁ。
引用返信 編集キー/
■41603 / inTopicNo.3)  Re[2]: XMLをCSVに変換する XSLT
□投稿者/ Travian (3回)-(2009/09/25(Fri) 13:51:57)
返信ありがとうございます。

■xmltocsv.xslt
<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ds="http://tempuri.org/DataSet1.xsd">
<xsl:template match="/">
<xsl:text>No.,品番,上限値,下限値
</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/ds:DataSet1/ds:ういうい">
<xsl:for-each select="ds:*">
<xsl:value-of select="text()"/>
<xsl:if test="position()!=last()">","</xsl:if>
<xsl:if test="position()=last()">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

としましたが、結果変わらずです。
名前空間の指定はこれで一致したはずなのですが。
なぜマッチしないのか><


> というか、正直 xslt よりスクリプトなり使って書き出した方が楽だと思うなぁ。

私も今そう感じております。。。

今までは、C#コード内でカンマと改行を挿入したものを吐き出してました。

今回、CSVの出力形式をC#のコンパイルなしで
自由に変更できるような仕様にする必要がありまして
引用返信 編集キー/
■41604 / inTopicNo.4)  Re[3]: XMLをCSVに変換する XSLT
□投稿者/ 魔界の仮面弁士 (1321回)-(2009/09/25(Fri) 14:18:55)
No41603 (Travian さん) に返信
> としましたが、結果変わらずです。
これでどうでしょう。

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet version="1.0" 
                xmlns:xsd="http://tempuri.org/DataSet1.xsd"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output
    encoding="shift_jis"
    omit-xml-declaration="yes"
    media-type="text/plain"
    indent="no"
    method="text"
  />
  <xsl:template match="/">
    <xsl:text>No.,品番,上限値,下限値</xsl:text>
    <xsl:apply-templates />
  </xsl:template>
  <xsl:template match="/xsd:DataSet1/xsd:ういうい">
    <xsl:for-each select="*">
      <xsl:text>"</xsl:text>
      <xsl:value-of select="text()"/>
      <xsl:text>"</xsl:text>
      <xsl:if test="position()!=last()">,</xsl:if>
      <xsl:if test="position()=last()">&#13;&#10;</xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>



> 名前空間の指定はこれで一致したはずなのですが。
> なぜマッチしないのか><
XSL 変換時のパラメータ指定にもよりますが、その XSLT を
初期設定のまま適用すると、こうなってしまうかも。

<?xml version="1.0" encoding="utf-8"?>No.,品番,上限値,下限値[改行]
[改行]
1","XBF222","52.0","48.0[改行]
[改行]
2","XBF222","42.0","48.0[改行]
[改行]
3","[改行]
[改行]

引用返信 編集キー/
■41607 / inTopicNo.5)  Re[4]: XMLをCSVに変換する XSLT
□投稿者/ Travian (4回)-(2009/09/25(Fri) 14:43:47)
ありがとうございます!

そのままですとこうなりました。
■data.csv
No.,品番,上限値,下限値"1","XBF222","52.0","48.0""2","XBF222","42.0","48.0""3",""

が、ちゃんとカンマで区切られて出てきたので感激です。

ちょっといじって下記のようにするといけました!

<?xml version="1.0" encoding="Shift_JIS" ?>
<xsl:stylesheet version="1.0"
xmlns:xsd="http://tempuri.org/DataSet1.xsd"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
encoding="shift_jis"
omit-xml-declaration="yes"
media-type="text/plain"
indent="no"
method="text"
/>
<xsl:template match="/">
<xsl:text>No.,品番,上限値,下限値&#13;&#10;</xsl:text>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="/xsd:DataSet1/xsd:ういうい">
<xsl:for-each select="*">
<xsl:text>"</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>"</xsl:text>
<xsl:if test="position()!=last()">,</xsl:if>
<xsl:if test="position()=last()"><xsl:text>&#13;&#10;</xsl:text></xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>


■data.csv
No.,品番,上限値,下限値
"1","XBF222","52.0","48.0"
"2","XBF222","42.0","48.0"
"3",""


あと
<xsl:output
encoding="shift_jis"
omit-xml-declaration="yes"
media-type="text/plain"
indent="no"
method="text"
/>

の部分は無しでも
欲しい結果が得られました。

なかなか難しいですね。
書き方にいろいろと癖があるような。。。
慣れないとミスの原因が発見できないですね。

もう少し挙動を探ってみたいと思いますが
解決済みにしておきます。

ありがとうございました。
引用返信 編集キー/
■41608 / inTopicNo.6)  Re[5]: XMLをCSVに変換する XSLT
□投稿者/ Travian (5回)-(2009/09/25(Fri) 14:44:12)
解決チェック忘れ
解決済み
引用返信 編集キー/
■41609 / inTopicNo.7)  Re[6]: XMLをCSVに変換する XSLT
□投稿者/ Travian (7回)-(2009/09/25(Fri) 14:54:51)
2009/09/25(Fri) 14:58:44 編集(投稿者)
2009/09/25(Fri) 14:58:41 編集(投稿者)

<xsl:template match="/ds:DataSet1/ds:ういうい">
<xsl:for-each select="ds:*">

<xsl:template match="/ds:DataSet1/ds:ういうい">
<xsl:for-each select="*">

それにしても、マッチしなかったのは
for_eachの selectの部分に余分?なds指定してたからなのでしょうか。

んんん。。。。

<xsl:template match="/ds:DataSet1/ds:ういうい">
<xsl:text>ああああああああああああ</xsl:text>
<xsl:for-each select="ds:*">

とかやっても
「ああああああああああああ」
は一切出力されず
無反応だったので
テンプレートにマッチしてないのかと思ったのですが。
なんなんだろう。。。
解決済み
引用返信 編集キー/
■41612 / inTopicNo.8)  Re[7]: XMLをCSVに変換する XSLT
□投稿者/ 魔界の仮面弁士 (1322回)-(2009/09/25(Fri) 15:31:27)
No41609 (Travian さん) に返信
>> の部分は無しでも
>> 欲しい結果が得られました。

Excel 2007 VBA から MSXML6 で初期設定のまま変換したところ、
当方環境では、output 要素を付けないと text ではなく、
xml 宣言付きで出力されてしまいました。

Set d = CreateObject("MSXML2.DOMDocument.6.0")
d.async = False
'd.preserveWhiteSpace = True
d.Load "C:\data.xml"

Set t = CreateObject("MSXML2.DOMDocument.6.0")
t.async = False
't.preserveWhiteSpace = True
t.Load "C:\xmltocsv.xslt"

Debug.Print d.transformNode(t)


一方、改行については、使用するパーサーによって、先の XSLT によって
改行が 2 重に出力されるもの(Visual Studio 2008 XSLT Debbuger)と、
改行が 1 つずつ出力される物(MSXML6 transformNode メソッド)とがありました。
この辺りは、パーサー側のホワイトスペース関連の設定値にも依存するのでしょうね。



> <xsl:template match="/ds:DataSet1/ds:ういうい">
> <xsl:text>ああああああああああああ</xsl:text>
> <xsl:for-each select="ds:*">

これは上位要素(<xsl:stylesheet>) で、名前空間
xmlns:ds="http://tempuri.org/DataSet1.xsd"
を設定しているという事なのですよね。

当方では、問題無く「ああああああああああああ」が出力されましたが…。


<xsl:stylesheet version="1.0"
xmlns:ds="http://tempuri.org/DataSet1.xsd"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" />
<xsl:template match="/ds:DataSet1/ds:ういうい">
<xsl:text>ああああああああああああ
</xsl:text>
<xsl:for-each select="ds:*">
<xsl:value-of select="name()"/>=[<xsl:value-of select="text()"/>]
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>


-------
ああああああああああああ
No.=[1]
品番=[XBF222]
上限値=[52.0]
下限値=[48.0]

ああああああああああああ
No.=[2]
品番=[XBF222]
上限値=[42.0]
下限値=[48.0]

ああああああああああああ
No.=[3]
品番=[]

解決済み
引用返信 編集キー/
■41614 / inTopicNo.9)  Re[8]: XMLをCSVに変換する XSLT
□投稿者/ Travian (9回)-(2009/09/25(Fri) 16:04:34)
> 一方、改行については、使用するパーサーによって、先の XSLT によって
> 改行が 2 重に出力されるもの(Visual Studio 2008 XSLT Debbuger)と、
> 改行が 1 つずつ出力される物(MSXML6 transformNode メソッド)とがありました。
> この辺りは、パーサー側のホワイトスペース関連の設定値にも依存するのでしょうね。

なんと。
属性指定無しの曖昧な表現は辞めたほうが良さそうですね。
ありがとうございます。


> これは上位要素(<xsl:stylesheet>) で、名前空間
> xmlns:ds="http://tempuri.org/DataSet1.xsd"
> を設定しているという事なのですよね。
>
> 当方では、問題無く「ああああああああああああ」が出力されましたが…。
>
>
> <xsl:stylesheet version="1.0"
> xmlns:ds="http://tempuri.org/DataSet1.xsd"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
> <xsl:output omit-xml-declaration="yes" />
> <xsl:template match="/ds:DataSet1/ds:ういうい">
> <xsl:text>ああああああああああああ
> </xsl:text>
> <xsl:for-each select="ds:*">
> <xsl:value-of select="name()"/>=[<xsl:value-of select="text()"/>]
> </xsl:for-each>
> </xsl:template>
> </xsl:stylesheet>

今、上記 xsltで試したところ
問題なく「ああああああ」出ました。
名前空間の指定も上記同様だったと思いますが
何かほかのミスをしていた可能性もあります。
いろいろいじったので再現不能です。。。

お時間取らせて申し訳ありませんでした。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -