2008年12月13日土曜日

'XHTML にインラインで埋め込まれた SVG'をやってみる.(XQueryも少し)

Cocoa-XMLで名前空間を利用する.
コード
  NSString *xhtmlURI= @"http://www.w3.org/1999/xhtml";
NSXMLNode *xhtmlNS= [NSXMLNode namespaceWithName:@"" stringValue:xhtmlURI];
NSString *svgURI= @"http://www.w3.org/2000/svg";
NSXMLNode *svgNS= [NSXMLNode namespaceWithName:@"" stringValue:svgURI];

NSXMLDocument* document= [NSXMLNode document];
[document setVersion:@"1.0"];
[document setCharacterEncoding:@"UTF-8"];

NSXMLElement* html= [NSXMLNode elementWithName:@"html" URI:xhtmlURI];
[document setRootElement:html];
[html addNamespace:xhtmlNS];
{
NSXMLElement* body= [NSXMLNode elementWithName:@"body" URI:xhtmlURI];
[html addChild:body];
{
NSXMLElement* h1= [NSXMLNode elementWithName:@"h1" URI:xhtmlURI];
[body addChild:h1];
[h1 addChild:[NSXMLNode textWithStringValue:@"XHTML にインラインで埋め込まれた SVG"]];
}
{
NSXMLElement* svg= [NSXMLNode elementWithName:@"svg" URI:svgURI];
[body addChild:svg];
[svg addNamespace:svgNS];
[svg addAttribute:[NSXMLNode attributeWithName:@"width" URI:svgURI stringValue:@"300px"]];
[svg addAttribute:[NSXMLNode attributeWithName:@"height" URI:svgURI stringValue:@"200px"]];

NSXMLElement* circle= [NSXMLNode elementWithName:@"circle" URI:svgURI];
[svg addChild:circle];
[circle addAttribute:[NSXMLNode attributeWithName:@"cx" URI:svgURI stringValue:@"150"]];
[circle addAttribute:[NSXMLNode attributeWithName:@"cy" URI:svgURI stringValue:@"100"]];
[circle addAttribute:[NSXMLNode attributeWithName:@"r" URI:svgURI stringValue:@"50"]];
[circle addAttribute:[NSXMLNode attributeWithName:@"fill" URI:svgURI stringValue:@"#ff0000"]];
}
}

NSString* output= [document XMLStringWithOptions:(NSXMLNodePrettyPrint|NSXMLNodeCompactEmptyElement)];
NSLog(@"%@", output);

結果
> <?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<h1>XHTML にインラインで埋め込まれた SVG</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="300px" height="200px">
<circle cx="150" cy="100" r="50" fill="#ff0000"/>
</svg>
</body>
</html>
この出力を保存する時の拡張子はhtmlでなくxmlにするとsafariでみれる.


ちなみに名前空間接頭辞を利用する方法
<svg:svg/>

はよろしくないらしい.
一般にこの方法で沢山のタグに接頭辞をつけるよりもデフォルト名前空間を再宣言した方が良いです。
https://developer.mozilla.org/ja/SVG/Namespaces_Crash_Course



でNSXMLNodeでこれをやろうとすると
 
NSXMLNode *svgNS= [NSXMLNode namespaceWithName:@"svg" stringValue:svgURI];
//svgNSを定義したdocumentに下記elementをaddしてもという意味
NSXMLElement* svg= [NSXMLNode elementWithName:@"svg" URI:svgURI];

と思うんだけどそんな出力にはならない.文字列的に無理矢理やるなら単純に
 
NSXMLElement* svg= [NSXMLNode elementWithName:@"svg:svg"];

となる.

ちなみにこれのやり方でも名前空間(URI)も実は設定さる.証拠に以下のようにな実験と結果がある.
コード
  NSString *xhtmlURI= @"http://www.w3.org/1999/xhtml";
NSXMLNode *xhtmlNS= [NSXMLNode namespaceWithName:@"" stringValue:xhtmlURI];
NSString *svgURI= @"http://www.w3.org/2000/svg";
NSXMLNode *svgNS= [NSXMLNode namespaceWithName:@"svg" stringValue:svgURI];

NSXMLDocument* document= [NSXMLNode document];
[document setVersion:@"1.0"];
[document setCharacterEncoding:@"UTF-8"];

NSXMLElement* html= [NSXMLNode elementWithName:@"html"];
[document setRootElement:html];
[html addNamespace:xhtmlNS];
[html addNamespace:svgNS];
{
NSXMLElement* body= [NSXMLNode elementWithName:@"body"];
[html addChild:body];
{
NSXMLElement* h1= [NSXMLNode elementWithName:@"h1"];
[body addChild:h1];
[h1 addChild:[NSXMLNode textWithStringValue:@"XHTML にインラインで埋め込まれた SVG"]];
}
{
NSXMLElement* svg= [NSXMLNode elementWithName:@"svg:svg"];
[body addChild:svg];
//[svg addNamespace:svgNS];
[svg addAttribute:[NSXMLNode attributeWithName:@"width" stringValue:@"300px"]];
[svg addAttribute:[NSXMLNode attributeWithName:@"height" stringValue:@"200px"]];

NSXMLElement* circle= [NSXMLNode elementWithName:@"svg:circle"];
[svg addChild:circle];
[circle addAttribute:[NSXMLNode attributeWithName:@"cx" stringValue:@"150"]];
[circle addAttribute:[NSXMLNode attributeWithName:@"cy" stringValue:@"100"]];
[circle addAttribute:[NSXMLNode attributeWithName:@"r" stringValue:@"50"]];
[circle addAttribute:[NSXMLNode attributeWithName:@"fill" stringValue:@"#ff0000"]];
}
}

NSString* output= [document XMLStringWithOptions:(NSXMLNodePrettyPrint|NSXMLNodeCompactEmptyElement)];
NSLog(@"%@", output);

NSString *xquery= @"declare namespace ns = \"http://www.w3.org/2000/svg\";//ns:*";
NSArray *objs= [document objectsForXQuery:xquery error:NULL];
NSEnumerator *objsEnum= [objs objectEnumerator];
NSXMLNode *obj;
while((obj= [objsEnum nextObject])!=nil) {
NSLog(@"%@", [obj XMLStringWithOptions:(NSXMLNodeCompactEmptyElement)]);
}
}

結果
> <?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">
<body>
<h1>XHTML にインラインで埋め込まれた SVG</h1>
<svg:svg width="300px" height="200px">
<svg:circle cx="150" cy="100" r="50" fill="#ff0000"/>
</svg:svg>
</body>
</html>

> <svg:svg width="300px" height="200px"><svg:circle cx="150" cy="100" r="50" fill="#ff0000"/></svg:svg>
> <svg:circle cx="150" cy="100" r="50" fill="#ff0000"/>


選択結果にcircle要素もでてくるのはおかしい?XQuery勉強不足…

XML出力の基本的なあたりはこちらに書いてみてあります.


間違いやお気づきの点がありましたらコメントもらえるとうれしいです.

0 件のコメント: