############################################################################
##
## Filename    : XMLSmartLite.pm
## Description : This module which is based on XML::Smart supplies an easy way to access/create XML data. 
## Author      : Luo Xi
## Company	   : Tianjin Zhongke Blue Whale Information Technologies Co., Ltd
## Copyright(C): Tianjin Zhongke Blue Whale Information Technologies Co., Ltd
##
## $LastChangedBy: 
## $LastChangedDate:
## $LastChangedRevision:
## $HeadURL: 
##
#############################################################################
package XMLSmartLite;
use Encode;
use XML::Smart;

BEGIN {
	use Exporter();
	use vars qw($VERSION @ISA @EXPORT);
	$VERSION = 0.01;
	@ISA = qw(Exporter);
	@EXPORT = qw(
		writeXmlFile
		readXmlFile
		formatSmartLiteData
	);
}

#
# formatXML() - Translate a xml HASH to string.
#
# ARGS:
#	$1, \%, xml hash
#	$2, $,	string
#	$3, $,	tab
#
# RET:
#	none
#
sub formatXML
{
	my ($data, $str, $r_num) = @_;

	if (ref($data) eq "HASH") {
		while (my ($k, $v) = each(%$data)) {
			if (ref($v) eq "ARRAY") {	
				foreach my $value(@$v) {					
					for (my $i = 0; $i < $r_num; $i++) {
						$str = $str."\t";
					}
				
					$str = $str."<$k";
			
					if (ref($value) eq "HASH") {
						if (scalar(keys(%$value)) > 0) {
							while (my ($k1, $v1) = each(%$value)) {
								if (ref($v1) ne "ARRAY" && $k1 ne "CONTENT") {
									$str = $str." $k1=".'"'."$v1".'"';
								}
							}
				
							$str = $str.">";

							if (exists($value->{"CONTENT"})) {
								$str = $str. $value->{"CONTENT"};
							} else {
								$str = $str."\n".formatXML($value, "", $r_num+1);
							
								for (my $i = 0; $i < $r_num; $i++) {
									$str = $str."\t";
								}
							}
						} else {
							$str = $str.">";
						}
					}
					
					$str = $str."</$k>\n";
				}
			}
		}
	}

	return $str;
}

#
# formatTree() - Translate XML::Smart HASH to own HASH.
#
# ARGS:
#	$1, \%, XML::Smart HASH
#
# RET:
#	$data	own HASH
#
sub formatTree
{
	my $data = shift;

	if (ref($data) eq "HASH") {
		if (scalar(keys(%$data)) > 0) {
			if (not exists($data->{"CONTENT"})) {
				while (my ($k, $v) = each(%$data)) {
					if (ref($v) eq "HASH") {
						$data->{$k} = [formatTree($v)];
					} else {
						$data->{$k} = formatTree($v);
					}
				}
			}
		}
	} elsif (ref($data) eq "ARRAY") {
		if (scalar(@$data) > 0) {
			foreach (@$data) {
				$_ = formatTree($_);
			}
		}
	}
	
	return $data;
}

#
# writeXmlFile() - Write hash to xml file.
#
# ARGS:
#	$1, \%, own xml HASH
#	$2, $, xml file
#	$3, $, encoding format, default is utf-8
#
# RET:
#	none
#
sub writeXmlFile
{
	my ($xml, $file, $encode) = @_;
	my $str = '<?xml version="1.0" encoding="utf-8"?>'."\n";
	
	if ($encode) {
		$str = '<?xml version="1.0" encoding="'.$encode.'"?>'."\n";
	} else {
		if (-e $file) {
			$str = qx{cat $file | head -n 1 2>&1};
		}
	}
	
	$str = formatXML($xml, $str, 0);
	
	if (open(TMP, "+>$file")) {
		print TMP $str;
		close(TMP);
	}
}

#
# readXmlFile() - Parse xml file to HASH.
#
# ARGS:
#	$1, $, xml file
#	$2, $, dest encoding format
#
# RET:
#	$xml = {
#		key => value,
#		......
#		key => value
#	}
#
sub readXmlFile
{
	my ($file, $encode) = @_;
	my $xml = {};
	my $str = "";
	
	if (open(FILE, $file)) {
		while(<FILE>) {
			$str = $str . $_;
		}
		
		close(FILE);
	}	
	
	if ($encode) {
		my $head = qx{cat $file | head -n 1 2>&1};
	
		chomp $head;
	
		if ($head =~ /encoding=["']([A-Za-z0-9\-]+)["']/) {
			my $s_encode = $1;
			
			if ($s_encode ne $encode) {
				$str = encode($encode, decode($s_encode, $str));
			}
		}
	}
	
	$xml = XML::Smart->new($str);
	$xml = $xml->pointer_ok();
	$xml = formatTree($xml);
	
	return $xml;
}

sub formatSmartLiteData
{
	my $data = shift;

	if (ref($data) eq "HASH") {
		if (! exists($data->{"CONTENT"})) {
			while (my ($key, $value) = each(%$data)) {
				$data->{$key} = formatSmartLiteData($value);
			}
		}

		$data = [$data];
	} elsif (ref($data) eq "ARRAY") {
		if (scalar(@$data) > 0) {
			foreach my $a(@$data) {
				if (ref($a) eq "HASH") {
					while (my ($key, $value) = each(%$a)) {
						$a->{$key} = formatSmartLiteData($value);
					}
				} else {
					$a = {"CONTENT" => $a};
				}
			}
		} else {
			$data = [{}];
		}
	} else {
		$data = [{"CONTENT" => $data}];
	}

	return $data;
}

1;
