- PR -

Xerces C++でDTD定義ファイルの参照先変更について

投稿者投稿内容
りた
会議室デビュー日: 2004/06/03
投稿数: 5
投稿日時: 2004-06-03 12:00
かなり困っています。

XercesDOMParserのparse()にてDOMDocumentを作成し、そのDOMDocument内のDocumentType定義を変更したいのです。

入力XML
<!DOCTYPE DICOM SYSTEM "./dicom.dtd">

出力XML
<!DOCTYPE DICOM SYSTEM "/tmp/dicom.dtd">

のように出力時に変更したいのですが、DOMDocumetnType部分を変更する方法がわかりません。

どなたかご存知でしょうか?
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2004-06-04 09:38
API がないなら
XSLTで恒等変換(最上位要素を xsl:copy-of)して
xsl:output doctype-system = string omit-xml-declaration = "no"
で変更できませんか?
りた
会議室デビュー日: 2004/06/03
投稿数: 5
投稿日時: 2004-06-04 13:22
MMXさま。
アドバイスありがとうございます。

一旦XMLファイルに出力したものをXSTL等で編集するのは、ちょっと都合が悪く、
なんとか【DOMDocument】内に登録されている情報を更新したいのです。
APIが無い時点で無理なのかもしれません・・・。

すみません、ありがとうございました!
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-06-04 15:16
引用:

りたさんの書き込み (2004-06-04 13:22) より:
一旦XMLファイルに出力したものをXSTL等で編集するのは、ちょっと都合が悪く、
なんとか【DOMDocument】内に登録されている情報を更新したいのです。
APIが無い時点で無理なのかもしれません・・・。


XSLTはファイルからファイルだけでなく、DOMからDOMへの変換もできますよ。
…とここまで書いてから、言語がC++だと気づいてXalan C++のAPI見てみました。
DOMのターゲットってないんですねえ。そうするとターゲットからDOMを構築するコードを書く
必要があるのかな。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2004-06-04 18:28
DOMプログラミング虎の巻
http://www.asahi-net.or.jp/~dp8t-asm/java/articles/XMLJava2/article.html

DOM1レベルでは
ノードタイプ依存処理
ノード ノードタイプ ノード名 値 属性 子
DocumentType DOCUMENT_TYPE_NODE ドキュメントタイプ名 null null ○
ですからどうしようも無いですね。

DOM2でも
IDL Definition
interface DocumentType : Node {
readonly attribute DOMString name;
readonly attribute NamedNodeMap entities;
readonly attribute NamedNodeMap notations;
// Introduced in DOM Level 2:
readonly attribute DOMString publicId;
// Introduced in DOM Level 2:
readonly attribute DOMString systemId;
// Introduced in DOM Level 2:
readonly attribute DOMString internalSubset;
};
書き換え不能ですね。

DOM3 では?

簡単なのはテキスト処理で文字列の頭部付け替え?か。
chack
常連さん
会議室デビュー日: 2002/11/18
投稿数: 48
お住まい・勤務地: 埼玉県
投稿日時: 2004-06-04 19:13
新しいDocumentTypeを定義したDOMDocumentを作って
そこに、元のDOMツリーをコピーする方法ではダメでしょうか。

コード:
// DOMDocument* srcDoc  <- 元のXML Document
DOMNode* srcRoot = srcDoc->getDocumentElement();

DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(L"Core");

DOMDocument* saveDoc = NULL;

try
{
  // create DOCTYPE node. <!DOCTYPE rootName SYSTEM "dtd file uri">
  const XMLCh* rootName = srcRoot->getNodeName();
  const XMLCh* dtdName = //dtdの名前
  DOMDocumentType* doctype = impl->createDocumentType(rootName, NULL, dtdName);

  saveDoc = impl->createDocument(0,        // root element namespace URI.
                                 rootName, // root element name
                                 doctype); // document type object (DTD).

  DOMNode* saveRoot = saveDoc->getDocumentElement();

  // ここでsaveDoc へ srcDoc のツリーをコピー
  // ...
  //

}
catch (...)
{
  if (saveDoc)
    saveDoc->release();
}



私が使っているのはIBMのxml4c 5.2.0ですが、Xerces でも同じだと思います。
(Xerces C++では Ver.2.4あたりに相当すると思います)

xml4cを使った、かなり前に書いたコードの抜粋です。
やはりDocumentTypeを変更する必要があり、このような手を使いました。
りた
会議室デビュー日: 2004/06/03
投稿数: 5
投稿日時: 2004-06-07 11:41
ukさま。
MMXさま。
 調査、コメントありがとうございます! 大変感謝いたします!

chackさま。
 本当にありがとうございます。
下記方法を思いついたのには恐れ入りました。

ついでで恐縮ですが、質問があります。
新しい[DOMDocument:saveDoc]を新規作成するところまでは理解できます。
コメントアウトされている[//ここでsaveDoc へ srcDoc のツリーをコピー]の処理なんですが、
saveRoot=srcRoot;
ってルートノードのアドレスを書き換えちゃってもOKですかね?
それとも1ノードずつ抜き出して1ノードずつ追加しないとだめなのでしょうか?
可能であれば、[//ここでsaveDoc へ srcDoc のツリーをコピー]の処理も教えていただけるととてもうれしいです。
もちろん企業秘密等の問題が無いコードであればですけど。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2004-06-07 14:09
importNode
で検索。
http://www.dbms.cs.gunma-u.ac.jp/~iwaki/thesis/node51.html
とか、いろいろ

この、場合は直代入でも動くと思うが、GCなどのメモリ回収でどうなるか?とか
深くコピーしていないので、新旧DOMの更新操作が混じります。

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