@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

WordMLからXMLに変換

投稿者投稿内容
hirotan
常連さん
会議室デビュー日: 2004/07/20
投稿数: 41
投稿日時: 2004-07-20 14:02
初めて投稿します。
よろしくお願いします。

実は今Office2003(Word)で保存したXMLははフォントが変わったところで、文章を切り離しています。段落の文字列を一まとめにしたXMLに変換しようと考えています。

やりたいことは、細かいフォントはなしにして、ボールド、イタリック等の文字ならばインラインの要素としてXMLの構造を持たせたXMLに変換したいと考えています。

例:WordMLの一部分
<w:r>
 <w:rPr>
  <w:rFonts w:hint="fareast"/>
  <wx:font wx:val="MS 明朝"/>
  <w:b/> ←ボールド指定
  <w:i/> ←イタリック指定
 </w:rPr>
 <w:t>ボールドイタリック</w:t> ←テキスト部分(この部分がボールドイタリックになる)
</w:r>

★XSLで変換後このような感じになってほしい(一段落の文字を一まとめにしたい)
<p>・・・<b><i>ボールドイタリック</i></b>・・・</p>

XSLでどのように書いたらよいかわかりません。
どなたか教えていただけませんでしょうか。

よろしくお願いします。



MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2004-07-20 14:54
w:t にマッチした時
自身の、親の、w:rPrの、中に
w:b があれば<b>
w:i があれば<i>
を発生させて
自身を吐き出す

をXSLTに書き下す。
---------------------------
Word のHTML保存して HTML Filter
http://pcweb.mycom.co.jp/news/2002/10/03/10.html
のほうが簡単かも

[ メッセージ編集済み 編集者: MMX 編集日時 2004-07-20 14:57 ]
hirotan
常連さん
会議室デビュー日: 2004/07/20
投稿数: 41
投稿日時: 2004-07-20 15:07
回答ありがとうございます。

早速試してみます。
hirotan
常連さん
会議室デビュー日: 2004/07/20
投稿数: 41
投稿日時: 2004-07-20 16:16
[quote]
MMXさんの書き込み (2004-07-20 14:54) より:
w:t にマッチした時
自身の、親の、w:rPrの、中に
w:b があれば<b>
w:i があれば<i>
を発生させて
自身を吐き出す

をXSLTに書き下す。

↑の書き下すところで苦戦しています。
たとえば下記のようなXMLの場合、どのように記述すればよいでしょうか。
★サンプルXML
<root>
 <p>
  <style>
   <font>MSゴシック</font>
   <bold />
   <italic />
  </style>
  <t>あいうえお</t>
 </p>
</root>

ためしに作ってみたXSLは下記のとおりです。
<xsl:template match="* | @* | text()">
 <xsl:copy>
  <xsl:apply-templates select="* | @* | text()"/>
 </xsl:copy>
</xsl:template>

<xsl:template match="style" />

<xsl:template match="t">
 <xsl:variable name="test">
  <xsl:call-template name="ttt"></xsl:call-template>
 </xsl:variable>
 <xsl:value-of select="$test" />
</xsl:template>

<xsl:template name="ttt">
 <xsl:choose>
  <xsl:when test="../style/bold">
   <b>
    <xsl:call-template name="ttt" />
   </b>
  </xsl:when>
  <xsl:when test="../style/italic">
   <i>
    <xsl:call-template name="ttt" />
   </i>
  </xsl:when>
  <xsl:otherwise>
   <xsl:value-of select="t" />
  </xsl:otherwise>
 </xsl:choose>
</xsl:template>

これだと無限ループしてしまいます。
だめなところをご指摘願えますでしょうか。
よろしくお願いします。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-07-20 17:20
引用:

hirotanさんの書き込み (2004-07-20 16:16) より:
<xsl:template name="ttt">
 <xsl:choose>
  <xsl:when test="../style/bold">
   <b>
    <xsl:call-template name="ttt" />
   </b>
  </xsl:when>
  <xsl:when test="../style/italic">
   <i>
    <xsl:call-template name="ttt" />
   </i>
  </xsl:when>
  <xsl:otherwise>
   <xsl:value-of select="t" />
  </xsl:otherwise>
 </xsl:choose>
</xsl:template>

これだと無限ループしてしまいます。
だめなところをご指摘願えますでしょうか。
よろしくお願いします。


    <xsl:call-template name="ttt" />
の部分でカレントのノードが変わっていないため、いつまでたっても同じところを呼び出すことに
なっているのでしょう。このように再帰処理をするのであれば、子孫ノードを渡していく必要が
ありますが、そもそも再帰処理が必要なのでしょうか。
hirotan
常連さん
会議室デビュー日: 2004/07/20
投稿数: 41
投稿日時: 2004-07-20 17:38
回答ありがとうございます。

word2003ではボールド・イタリックなどによって、文章が分かれていて、それを一段落ごとの要素にまとめたいというのが最終的な目的なのですが、これらをインラインタグとして処理をするのにてこずっています。

文字列が入っているところが最下層になるので、さらに再帰ということは考えなくてもよさそうです。

いろいろ試してみて、もう一度作って見ました。
下記のように書くと一応できたみたいなのですが、このような書き方で果たしてよいものかどうか。。。御指摘等あればよろしくお願いします。

例:以前のサンプルXMLで実行させる場合

<xsl:template match="t">
 <xsl:variable name="boldnode">
  <xsl:choose>
   <xsl:when test="../style/bold">
    <b><xsl:apply-templates /></b>
   </xsl:when>
   <xsl:otherwise>
    <xsl:apply-templates />
   </xsl:otherwise>
  </xsl:choose>
 </xsl:variable>

 <xsl:variable name="italicnode">
  <xsl:choose>
   <xsl:when test="../style/italic">
    <i><xsl:copy-of select="$boldnode"/></i>
   </xsl:when>
   <xsl:otherwise>
    <xsl:copy-of select="$boldnode"/>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:variable>

<p><xsl:copy-of select="$italicnode"/></p>
</xsl:template>


MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2004-07-20 18:40
<?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" version="1.0" encoding="UTF-8" indent="no"/>

<!-- 変換定数表 charatt.xml node-set関数が使えるなら そのほうが簡単 -->
<!-- <CONST><s>bold</s><s>b</s><s>italic</s><s>i</s></CONST> -->
<xsl:variable name="charatt" select="document('charatt.xml')"/>

<xsl:template match="* | @* | text()">
 <xsl:copy>
  <xsl:apply-templates select="* | @* | text()"/>
 </xsl:copy>
</xsl:template>

<xsl:template match="style"/>

<xsl:template match="t">
  <xsl:call-template name="ttt">
<xsl:with-param name="charatt" select="$charatt/CONST/*"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="ttt">
<xsl:param name="charatt"/>++
<xsl:variable name="att" select="$charatt[1]/text()"/><!-- CAR -->
<xsl:value-of select="$att"/>
<xsl:choose>
<xsl:when test="../style/*[name()=$att]">@@
<xsl:element name="{$charatt[2]/text()}">
  <xsl:call-template name="ttt"><!-- 一度に1要素の末尾再帰 -->
<xsl:with-param name="charatt" select="$charatt[position()>2]"/>
<!-- CDR -->
</xsl:call-template>
</xsl:element>
  </xsl:when>
<xsl:otherwise>--
   <xsl:value-of select="."/><!-- カレントは動かさないように -->
  </xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
--------------------- トレース用の文字列が入っています
多重囲みを発生させるので、不定個数では どうしても再帰になりやすい
-----------
先にfor-each で bold italic を収集しておいても再帰になる
==================
WordML を処理するには name() と local-name() を使い分けます
$att は w: 無しを仮定している


[ メッセージ編集済み 編集者: MMX 編集日時 2004-07-20 18:57 ]
hirotan
常連さん
会議室デビュー日: 2004/07/20
投稿数: 41
投稿日時: 2004-07-20 21:53
回答ありがとうございます。

ちょっと難しくなってきたので、教えていただいた内容を踏まえて勉強してみます。
またわからなくなったら投稿したいと思いますので、よろしくお願いします。

スキルアップ/キャリアアップ(JOB@IT)