너무 오랫동안 포스팅을 하지 못했네요. 이러다 감까지 상실하겠습니다. ㅎㅎ
성격상 한가지 일에만 몰두하는 스타일이라 코드 짜면서 블로그에 글 올리는게 쉽지가 않네요. (게을러서 인가요..)
암튼 간만에 얼마 전에 만들어 봤던게 있어 살짝 올려 봅니다. XML뷰어 인데요. Node element, attribute, NameSpace, text Node, Comment로 구분하여 보여줍니다. 주소입력창에 직접 xml 경로 입력하셔서 테스트해 보세요..^^
소스는 아래에 있습니다. (Flex SDK4)
<mx:AdvancedDataGrid xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
rowHeight="18"
fontSize="12"
paddingBottom="0"
paddingTop="0"
defaultLeafIcon="{null}"
folderClosedIcon="{null}" folderOpenIcon="{null}"
disclosureClosedIcon="{openIcon}"
disclosureOpenIcon="{closeIcon}"
iconFunction="getIconClass"
displayItemsExpanded="true"
>
<mx:columns>
<mx:AdvancedDataGridColumn dataField="name" labelFunction="{getLabelString}"/>
<mx:AdvancedDataGridColumn dataField="value" labelFunction="{getValueString}"/>
</mx:columns>
<fx:Script>
<![CDATA[
import mx.collections.HierarchicalData;
override protected function commitProperties() : void
{
super.commitProperties();
if(_sourceChanged){
_sourceChanged = false;
sourceChanged();
}
}
//---------------------------------
// 라벨 메서드
//---------------------------------
[Bindable]
private var internalNS:Namespace = ConvertXML.ns_information;
/**
* name 컬럼의 내용표시 방법.
*/
private function getLabelString(item:Object, column:AdvancedDataGridColumn):String
{
var node:XML = item as XML;
var label:String = node.@internalNS::name;
return label;
}
/**
* value 컬럼의 내용표시 방법.
*/
protected function getValueString(item:Object, column:AdvancedDataGridColumn):String
{
var node:XML = item as XML;
var label:String = node.@internalNS::value;
var pattern:RegExp = /\s*(\n|\r)+\s*/g;
label = label.replace(pattern, " ");
return label;
}
//---------------------------------
// 아이콘
//---------------------------------
/** 마이너스 버튼 아이콘.*/
[Bindable]
[Embed(source="com/vulcan/assets/closeNodeIcon.png")]
private var closeIcon:Class;
/** 플러스 버튼 아이콘.*/
[Bindable]
[Embed(source="com/vulcan/assets/openNodeIcon.png")]
private var openIcon:Class;
/** child 있는 Element 표시 아이콘.*/
[Bindable]
[Embed(source="com/vulcan/assets/elementComplexIcon.png")]
private var elementComplexIcon:Class;
/**child 없는 표시 아이콘.*/
[Bindable]
[Embed(source="com/vulcan/assets/elementSimpleIcon.png")]
private var elementSimpleIcon:Class;
/**comment 표시 아이콘.*/
[Bindable]
[Embed(source="com/vulcan/assets/commentIcon.png")]
private var commentIcon:Class;
/** attribute 표시 아이콘.*/
[Bindable]
[Embed(source="com/vulcan/assets/attributeIcon.png")]
private var attributeIcon:Class;
/** text 노드 표시 아이콘.*/
[Bindable]
[Embed(source="com/vulcan/assets/textIcon.png")]
private var textIcon:Class;
/** nameSpace 표시 아이콘.*/
[Bindable]
[Embed(source="com/vulcan/assets/nameSpaceIcon.png")]
private var nameSpaceIcon:Class;
/**표시 아이콘 선별 메서드.*/
private function getIconClass(item:Object):Class
{
var node:XML = item as XML;
var iconClass:Class;
var type:String = node.@internalNS::type;
if(type == ConvertXML.ELEMENT_COMPLEX){
iconClass = elementComplexIcon;
}else if(type == ConvertXML.ELEMENT_SIMPLE){
iconClass = elementSimpleIcon;
}else if(type == ConvertXML.ATTRIBUTE){
iconClass = attributeIcon;
}else if(type == ConvertXML.COMMENT){
iconClass = commentIcon;
}else if(type == ConvertXML.TEXT){
iconClass = textIcon;
}else if(type == ConvertXML.NAMESPACE){
iconClass = nameSpaceIcon;
}else{
iconClass = null;
}
return iconClass;
}
//---------------------------------
// 소스 xml
//---------------------------------
private var _sourceChanged:Boolean = false;
private var _source:XML;
/** 읽어들일 XML 객체.*/
[Bindable]
public function get source():XML
{
return _source;
}
public function set source(value:XML):void
{
if(value == null){
_source = value;
dataProvider = null;
}else{
// 적절한 xml 형태로 변환한다.
_source = value.copy();
ConvertXML.input(_source);
var dp:HierarchicalData = new HierarchicalData();
dp.source = _source;
dataProvider = dp;
}
_sourceChanged = true;
invalidateProperties()
}
private function sourceChanged():void
{
dispatchEvent(new Event("sourceChanged"));
}
]]>
</fx:Script>
</mx:AdvancedDataGrid>
{
public class ConvertXML
{
public function ConvertXML()
{
}
public static var uri_information:String = "http://vulcan9.tistory.com/internal_convert_xml";
public static var prefix_information:String = "newCreateNode"; //internal_xmlViewer_convert_node
public static var ns_information:Namespace = new Namespace(prefix_information, uri_information);
// 새로 생성되는 노드의 형태.
static public const ELEMENT_COMPLEX:String = "element_complex";
static public const ELEMENT_SIMPLE:String = "element_simple";
static public const ATTRIBUTE:String = "attribute";
static public const COMMENT:String = "comment";
static public const TEXT:String = "text";
static public const NAMESPACE:String = "namespace";
////////////////////////////////////
// XML 형태를 Tree 구조에 적합하도록 변환
////////////////////////////////////
/**
* 입력된 xml 데이터를 트리구조로 표시하기 알맞은 형태로 변환한다.
* 변환되는 내용은 다음과 같다.
*
* @example
* <listing version="3.0" >
* 1. attribute을 Node 로 바꾼다
*
* <properties description="사용자가 설정 가능한 Property 속성 리스트">
* 다음으로 변환
* <properties>
* <internal:node internal:type="attribute" internal:name="description" internal:value="사용자가 설정 가능한 Property 속성 리스트" />
* ...
* </properties>
*
* 2. comment 를 새로운 Node 로 바꾼다.
*
* <!-- 주석 내용 -->
* 다음으로 변환
* <internal:node internal:type="comment" internal:name="comment" internal:value="주석내용" />
*
* 3. text 노드를 제거하고 상위 노드의 값으로 바꾼다. text 값이 XmlList일 수도 있다.
*
* <이름>값</이름>
* 다음으로 변환
* <internal:node internal:type="text" internal:name="이름" internal:value="값" />
*
* 4. nameSpace 선언부 내용을 Node 내용으로 바꾼다.
*
* < ... xmlns:prefix="uri" ...>
* 다음으로 변환
* <internal:node internal:type="namespace" internal:name="prefix" internal:value="uri"/>
*
* </listing>
*
* @param copyedXml 전달받은 xml은 내용(구조)이 일부 변경 될 수도 있으므로 copy() 본을 전달하는것이 좋다.
*/
// type, name, value 속성을 모든 노드에 제공한다.
static public function input(copyedXml:XML):XML
{
var xml:XML = new XML(<root></root>);
xml.setNamespace(ns_information);
xml.appendChild(copyedXml);
convert_IN(copyedXml);
//trace(copyedXml)
return xml;
}
//-------------------------------------
// Element
//-------------------------------------
/** xml을 트리에 표시하기에 적합한 형태로 변환한다.*/
static private function convert_IN(node:XML):void
{
// 필요한 노드 추가
var parent:XML = node.parent();
var nodeKind:String = node.nodeKind();
if(nodeKind == "element"){
// 텍스트 노드값 임시 저장
var type:String;
var value:String;
if(node.hasSimpleContent() && node.attributes().length() == 0){
type = ELEMENT_SIMPLE;
value = node.text().toXMLString();
}else{
type = ELEMENT_COMPLEX;
value = "";
}
var ns:Namespace = node.namespace();
var name:String = node.localName();
if(ns.prefix) name = ns.prefix + " : " + name;
// *********************************************
// 자식 노드에 대해서 재귀호출
var list:XMLList = node.children();
var len:Number = list.length();
for(var i:int=0; i<len; i++)
{
convert_IN(list[i]);
}
// *********************************************
// 기존 Attribute을 Node로 표시하고 제거
var attributeList:XMLList = attributeToNode(node);
// 새로운 Attribute에 정보 추가
node.@ns_information::type = type;
node.@ns_information::name = name
node.@ns_information::value = value;
// attribute 노드 추가 (자식노드 재귀호출 후에 실행해야함.)
node.prependChild(attributeList);
// nameSpace Declarations 항목
var nameSpaceList:XMLList = nsDeclaration(node);
if(nameSpaceList.length() > 0) node.prependChild(nameSpaceList);
}else if(nodeKind == "text"){
var attLength:Number = parent.attributes().length();
var isSimpleNode:Boolean = parent.hasSimpleContent();
var txt:XMLList;
if(isSimpleNode && attLength == 0){
// 그냥 노드 삭제 - parent Element에 text값 표시됨.
// Text항목은 element 노드에서 이미 표시되었다.
}else{
// 기존 text을 Node로 표시하고 제거
txt = textToNode(node);
parent.insertChildBefore(node, txt);
}
// 노드 제거
var idx:Number = node.childIndex();
delete parent.children()[idx];
}else if(nodeKind == "comment"){
// Comment를 Node로 표시하기
var comm:XMLList = commentToNode(node);
parent.insertChildBefore(node, comm);
// 노드 제거
var ix:Number = node.childIndex();
delete parent.children()[ix];
}
}
//-------------------------------------
// Attribute
//-------------------------------------
/**
* attribute을 attribute Node 로 바꾼다
*/
static private function attributeToNode(attributeNode:XML):XMLList
{
// attributeNode 의 내용에 따라 attribute에 해당하는 노드를 생성한다.
var list:XMLList = attributeNode.attributes();
if(list.length() < 1) return <></>;
var xml:XML = getTempXML();
var attribute:XML;
var name:String;
for(var prop:String in list){
attribute = XML(list[prop]);
//name = ns_information.prefix + "::" + attribute.name();
name = attribute.name();
//trace(name, " : ", attribute);
var node:XML = getTempNode(ATTRIBUTE, name, attribute);
xml.appendChild(node);
// attribute은 제거한다.
delete attributeNode.@[name];
}
return xml.children();
}
//-------------------------------------
// Text
//-------------------------------------
/**
* text 노드를 제거하고 상위 노드의 값으로 바꾼다. text 값이 XmlList일 수도 있다.
*/
static private function textToNode(texttNode:XML):XMLList
{
// text 내용
var content:String = texttNode.toXMLString();
// 새로운 comment 노드를 생성한다.
var xml:XML = getTempXML();
var node:XML = getTempNode(TEXT, "", content);
xml.appendChild(node);
return xml.children();
}
//-------------------------------------
// NameSpace
//-------------------------------------
/**
* nameSpace 선언부 내용을 노드 내용으로 바꾼다.
*/
static private function nsDeclaration(nsNode:XML):XMLList
{
var xml:XML = getTempXML();
var list:Array = nsNode.namespaceDeclarations();
var len:Number = list.length;
var ns:Namespace;
for (var i:uint = 0; i<len; i++) {
ns = list[i];
var prefix:String = ns.prefix;
if (prefix == "") {
prefix = "(default)";
continue;
}
var node:XML = getTempNode(NAMESPACE, prefix, ns.uri);
xml.appendChild(node);
}
return xml.children();
}
//-------------------------------------
// Comment
//-------------------------------------
/**
* comment 를 새로운 comment 노드로 바꾼다.
*/
// commentNode 의 내용으로 comment 노드를 구성한다.
static private function commentToNode(commentNode:XML):XMLList
{
// comment 내용
var content:String = commentNode.toXMLString()
// 새로운 comment 노드를 생성한다.
var xml:XML = getTempXML();
var node:XML = getTempNode(COMMENT, "", content);
xml.appendChild(node);
return xml.children();
}
///////////////////////////////////
// 구체적인 노드로 구성한다.
///////////////////////////////////
static private function getTempXML():XML
{
var xml:XML = new XML(<data></data>);
xml.setNamespace(ns_information);
return xml;
}
static private function getTempNode(type:String, name:String, value:String):XML
{
var node:XML = new XML(<node></node>);
node.setNamespace(ns_information);
//xml.appendChild(node);
node.@ns_information::type = type;
node.@ns_information::name = name;
node.@ns_information::value = value;
return node;
}
////////////////////////////////////
// End
////////////////////////////////////
}
}
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
xmlns:xmls="com.vulcan.viewers.xmls.*"
width="600" height="400"
applicationComplete="init();">
<s:Label y="19" text="XML Path : " left="14"/>
<s:TextInput y="11" id="pathBox" right="88" left="75" text="http://vulcan9.tistory.com/rss" enter="onClick();"/>
<s:Button y="11" label="Button" height="20" id="loadBtn" click="onClick();" right="10"/>
<s:HGroup right="10" left="10" top="41" bottom="10">
<mx:TextArea text="Source" id="originalSource" width="100%" height="100%" editable="false" selectable="false" wordWrap="false"/>
<xmls:XmlViewer id="XV" width="100%" height="100%" source="{loadXML}"/>
</s:HGroup>
<fx:Script>
<![CDATA[
import spark.components.supportClasses.ItemRenderer;
import com.vulcan.viewers.items.ItemViewerEvent;
private function init():void
{
percentWidth=100;
percentHeight=100
pathBox.setFocus();
}
//---------------------------------
// XML
//---------------------------------
[Bindable]
private var loadXML:XML = new XML();
private function onClick():void
{
var XML_URL:String = pathBox.text;
var url:URLRequest = new URLRequest(XML_URL);
var loader:URLLoader = new URLLoader(url);
loader.addEventListener(Event.COMPLETE, onLoad);
loader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
}
private function onLoad(event:Event):void
{
var str:String = "";
try {
var loader:URLLoader = URLLoader(event.target);
loadXML = XML(loader.data);
str = loadXML.toXMLString();
originalSource.text = str;
}
catch(error:Error){
//throw new Error( "Class must embed an XML document containing valid mark-up. " + error.message );
str = "Class must embed an XML document containing valid mark-up. " + error.message + "\n";
originalSource.text += str;
}
finally{
//
}
}
private function onIOError(event:Event):void
{
originalSource.text += "XML 로드실패! \n xml load IO Error\n";
}
private function onSecurityError(event:Event):void
{
originalSource.text += "XML 로드실패! \n xml load Security Error\n";
}
]]>
</fx:Script>
</s:Application>
'Blog > 나의 작업물' 카테고리의 다른 글
Docking system 소스 받기 (6) | 2010.08.10 |
---|---|
Naver 개발자 센터에 Docking system 소스를 공개합니다. (1) | 2010.08.10 |
플래시 EBook 저작툴(2) (4) | 2010.07.15 |
플래시 EBook 저작툴(1) (4) | 2010.07.15 |
Docking system Framework (flex4) (2) | 2010.05.01 |