プロが教える店舗&オフィスのセキュリティ対策術

XMLドキュメントにXSLを適用すると
XSL中の改行やタブがそのまま反映されてしまいます。

改行を無くすと1行が長くなってしまい編集が大変で困っています。

どうしたらよいのでしょうか?

XSL:
<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xml:space="default" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each select="//z:row">
<xsl:choose>
<xsl:when test="(@MACHINE='DELL')">
</xsl:when>
<xsl:when test="(@MACHINE='APPLE')">
</xsl:when>
<xsl:when test="(@MACHINE='HP')">
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@MACHINE" />,
<xsl:value-of select="substring(@PARTS_NO,1,1)" />-<xsl:value-of select="substring(@PARTS_NO,2,3)" />-<xsl:value-of select="substring(@PARTS_NO,5,3)" />-<xsl:value-of select="substring(@PARTS_NO,8,2)" />,<xsl:value-of select="@STATUS" />,<xsl:value-of select="@STOCK_NUM" /><xsl:text>&#xA;</xsl:text>
<xsl:if test="not(@MACHINE=following-sibling::z:row/@MACHINE)">
<xsl:text>,&#xA;</xsl:text>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

A 回答 (4件)

状況が再現し、一応除去もできるようにはなりましたけどなんか釈然としません。


やってみた方法は、XSLを2段階適用するというやり方で
transformNodeToObjectを使って別のXML(output method="xml")に変換し
(XSLで一行分のレコードをxsl:elementで1つのエレメントにする)
transformNodeで
<xsl:value-of select="translate(., '

', '')" />
みたいにして作成したエレメントから空白文字を取り除く+<xsl:text>
</xsl:text>
(output methid="text")
するというようなやり方です。
でも、いちいちこんなやり方するなら、別に一行に書けばいいんじゃないかとか思えて釈然としません。
ところで、
std::string s = pXMLDOMDoc->transformNode(pXSLDOMDoc);
replace(s, std::string("\r\n"), std::string("\n"));
ってうまくいきますか?
こういう置換がプログラムでできるなら、
transformNodeで出力したものからタブと取り除くのも難しくないと思うのですが、
スタイルシートで、:CR:観たいなものをレコード区切りとして付与して
スペース、タブ、改行を取り除いた後
:CR:を改行に置換するというような手順でいいような気がします。
どっちかというと、そういうプログラムで(整形)処理するのが、簡単でいいような気がするのですが。
    • good
    • 0
この回答へのお礼

ありがとうございます、確かに仰られるように何かすっきりしません(笑

>replace(s, std::string("\r\n"), std::string("\n"));
上記の置換はうまく動きます。

もう少し粘ってみますが、だめなら上記のお知恵を拝借させて頂きたいと思います。

本当にご親切にありがとうございます。

お礼日時:2005/09/13 14:09

すいません、XMLの方も挙げて下さい

この回答への補足

すいません、XMLはこちらになります。

<xml xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
<s:ElementType name="row" content="eltOnly" rs:CommandTimeout="30">
<s:AttributeType name="MACHINE" rs:number="1" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:AttributeType name="PARTS_NO" rs:number="2" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:AttributeType name="STATUS" rs:number="3" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:AttributeType name="STOCK_NUM" rs:number="3" rs:nullable="true" rs:write="true">
<s:datatype dt:type="string" rs:dbtype="str" dt:maxLength="8190"/>
</s:AttributeType>
<s:extends type="rs:rowbase"/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row MACHINE="APPLE" PARTS_NO="1" STATUS="WAIT" STOCK_NUM="4"/>
<z:row MACHINE="DELL" PARTS_NO="2" STATUS="ENOUGH" STOCK_NUM="43"/>
<z:row MACHINE="NEC" PARTS_NO="3" STATUS="EMPTY" STOCK_NUM="1"/>
<z:row MACHINE="HP" PARTS_NO="4" STATUS="WAIT" STOCK_NUM="3"/>
</rs:data>
</xml>

補足日時:2005/09/12 17:07
    • good
    • 0

#1>実はアプリケーション本体も私が作っています。


#1でいうところのアプリケーションは、XML(XSL)パーサーのことです。

#1の回答をした時は、実際に試してみるデータがなかったので、実際に試さずにコメントしただけなのですが、
補足をいただいて、適当なデータで試してみたら
>XMLドキュメントにXSLを適用すると
>XSL中の改行やタブがそのまま反映されてしまいます。
が再現しませんでした。(私のテストが悪いのかもしれませんが)
できたら、XMLのデータやプログラム?を補足で挙げてもらえませんか

>XSLを読み込む際に空白を維持するか指定できるのでしょうか?
ちょっと調べてみたのですがそういう指定は無いような感じです。
もともとそういうタブのインデントとか空白文字って無視される(パーサーにとっては意味がない)はずなので
あんまり関係ないと思います。

どっちにしても(最悪そういう出力であっても)
msxsl:scriptとかを使うとか、実際のプログラムでタブや改行を取り除くのはそれほど難しくもないんじゃないかと思います

この回答への補足

>#1でいうところのアプリケーションは、XML(XSL)パーサーのことです。
それだと難しそうですね、xml:space試してみましたがダメでした。

>msxsl:scriptとかを使うとか、実際のプログラムでタブや改行を取り除くのはそれほど難しくもないんじゃないかと思います

msxsl:scriptというものがあるのですね、xsl内で関数が定義でき、使用できるという感じなのでしょうか。
勉強になります、調べてみます。

ソースは以下のような感じです。
_RecordsetPtr pRecordset;
IXMLDOMDocumentPtr pXMLDOMDoc;

[ADOの接続省略]
char szSql[] = "select MACHINE, PARTS_NO, STATUS, STOCK_NUM from ZAIKO";
pRecordset = adoCtrl.OpenRecordSet(szSql);
if(pRecordset != NULL){
pXMLDOMDoc.CreateInstance(__uuidof(DOMDocument));
pRecordset->Save(pXMLDOMDoc.GetInterfacePtr(), adPersistXML);

}else {
return "定義済みのerror code";
}

IXMLDOMDocumentPtr pXSLDOMDoc;

pXSLDOMDoc.CreateInstance(__uuidof(DOMDocument));
pXSLDOMDoc->put_async(VARIANT_FALSE);
pXSLDOMDoc->validateOnParse = FALSE;
pXSLDOMDoc->load( _variant_t("XSLファイルのパス") );

std::string s = pXMLDOMDoc->transformNode(pXSLDOMDoc);

replace(s, std::string("\r\n"), std::string("\n"));

std::ofstream fout("csvファイルのパス", std::ios::trunc);
fout << s.data() << std::endl;
fout.close();

補足日時:2005/09/12 15:52
    • good
    • 0

原因の1つは


xml:space="default"
ではないかと思います。
XMLでは通常空白やタブ、改行は無視されますが、
xml:spaceでそうした空白文字の扱いを指定できます。
defaultは、扱いをアプリケーションに任せるという指定です。(無視するという指定のは既定なので、ないです)
なので、指定自体をやめるというのが1つの方法ですが、
アプリケーション自体が空白文字を保持するのであれば、
XSL(の指定)ではどうしようもないですね。
スクリプトで処理してやるというのも1つの方法だと思いますが・

この回答への補足

BLUEPIXYさんありがとうございます。

実はアプリケーション本体も私が作っています。
MSXML3.0を使用しているのですが、こちらでXSLを読み込む際に空白を維持するか指定できるのでしょうか?

補足日時:2005/09/12 08:54
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!