Type TNumbering = Class
	//项目编号
	Function Create(docx);
	Begin
		docx_ := docx;
		numberingXml_ := docx.Zip().Get('word/numbering.xml');
		if not ifObj(numberingXml_) then Begin
			xmlData := TOfficeTemplate('numbering/numbering.xml');
			if ifString(xmlData) then Begin
				docx.Zip().Add('word/numbering.xml', xmlData);
				rels := 'word/_rels/document.xml.rels';
				relsObj := docx.Zip().Get(rels);
				[rId, target] := class(TSXml).FindRelationshipRid(relsObj, '');
				rId ++;
				class(TSXml).AddRelationshipRid(relsObj, 'numbering.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering', 'rId' $ rId);
				contentType := docx.Zip().Get('[Content_Types].xml');
				class(TSXml).AddOverrideContentType(contentType, '/word/numbering.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml');
				numberingXml_ := docx.Zip().Get('word/numbering.xml');
			End;
		End;
		maxAbstractNumId_ := 0;
		maxNumId_ := 1;
		numStyleObjs_ := array();
		numIdMap_ := array();
		bullet_ := array();
		hash_ := array();
		bulletDefine_ := array("ef82b2","ef81b5","ef83bc","ef81b6","ef81ac","ef8398","ef81ae");//缺省项目符号文字内容（utf8 -> hex16）
		if ifObj(numberingXml_) then Begin
			numbering := numberingXml_.FirstChildElement('w:numbering');
			if ifObj(numbering) then Begin
				node := numbering.FirstChildElement('w:abstractNum');
				numNode := numbering.FirstChildElement('w:num');
			End;
			while ifObj(node) do Begin
				o := TOfficeObj('TNumStyle');
				o.Init(node);
				nsid := o.Value('nsid');
				if nsid then
					hash_[nsid] := 1;
				tmpl := o.Value('tmpl');
				if tmpl then
					hash_[tmpl] := 1;
				id := StrToIntDef(o.abstractNumId, 0);
				if id >= 0 and maxAbstractNumId_ <= id then
					maxAbstractNumId_ := id + 1;
				_addStyle(o);
				lastAbstractNumStyle_ := node;
				node := node.NextElement('w:abstractNum');
			End;
			while ifObj(numNode) do Begin
				idStr := numNode.GetAttribute('w:numId');
				id := StrToIntDef(idStr, 0);
				if id > 0 and maxNumId_ <= id then
					maxNumId_ := id + 1;
				abstractNumIdNode := numNode.FirstChildElement('w:abstractNumId');
				if ifObj(abstractNumIdNode) then
					numIdMap_[idStr] := abstractNumIdNode.GetAttribute('w:val');
				numNode := numNode.NextElement('w:num');
			End;
		End;
	End;
	
	///新生成numId
	///levelType：字符串，bullet、singleLevel、multilevel
	///fmt：项目格式，取值范围：bullet:0-6；singleLevel：(decimal、chineseCounting)；multilevel：decimal
	///返回：numId
	Function NumberId(levelType, fmt);
	Begin
		style := NumberStyle(levelType, fmt);
		if not ifObj(style) then
			return -1;
		num := TOfficeObj('TNumber');
		num.numId := maxNumId_++;
		num.abstractNumId := style.Id;
		numberingXml_.FirstChildElement('w:numbering').InsertEndChild(num.Marshal());
		numIdMap_[''$num.numId] := num.abstractNumId;
		return num.numId;
	End;
	
	///根据numId获取TNumStyle对象（已存在）
	///返回：TNumStyle对象
	Function NumberStyle(numId);overload;
	Begin
		abstractNumId := numIdMap_['' $ numId];
		if abstractNumId then Begin
			return numStyleObjs_[abstractNumId];
		End;
		return nil;
	End;
	
	//获取TNumStyle对象，如果不存在插入系统缺省
	Function NumberStyle(levelType, fmt);overload;
	Begin
		if levelType = 'bullet' then Begin
			if fmt < 0 or fmt > 6 then return nil;
			k := bulletDefine_[fmt];
			o := bullet_[k];
			if ifObj(o) then 
				return o;
			//不存在，插入缺省项目编号
			return AddDefaultStyle('bullet' $ fmt);
		End;
		
		if lowercase(levelType) = 'singlelevel' and lowercase(fmt) = 'decimal' then Begin
			if ifObj(singleNumLevel_) then
				return singleNumLevel_;
			return AddDefaultStyle('singleNumLevel-decimal');
		End;
		
		if lowercase(levelType) = 'singlelevel' and lowercase(fmt) in array('chinese','chinesecounting','cn','china') then Begin
			if ifObj(singleCNLevel_) then
				return singleCNLevel_;
			return AddDefaultStyle('singlelevel-chineseCounting');
		End;
		
		if lowercase(levelType) = 'multilevel' and lowercase(fmt) = 'decimal' then Begin
			if ifObj(multiNumLevel_) then
				return multiNumLevel_;
			return AddDefaultStyle('multilevel-decimal');
		End;
		return nil;
	End;

	///返回：TNumStyle全部对象列表array('id1':obj1,'id2':obj2);
	Function Numberings();
	Begin
		return numStyleObjs_;
	End;

	///新添加项目样式
	///xmlStr：xml字符串
	///返回：TNumStyle对象
	Function AddStyleByInnerXml(xmlStr);
	Begin
		if ifObj(lastAbstractNumStyle_) then
			node := numberingXml_.FirstChildElement('w:numbering').InsertAfterChild(lastAbstractNumStyle_, xmlStr);
		else
			node := numberingXml_.FirstChildElement('w:numbering').InsertFirstChild(xmlStr);
		node.SetAttribute('w:abstractNumId', maxAbstractNumId_++);
		lastAbstractNumStyle_ := node;
		o := TOfficeObj('TNumStyle');
		o.Init(node);
		_addStyle(o);
		_setNsId(o);
		return o;
	End;

	///新添加项目样式
	///o：TNumStyle对象
	///返回：TNumStyle对象
	Function AddStyle(o);
	Begin
		if ifObj(o) then Begin
			o.abstractNumId := maxAbstractNumId_++;
			if ifObj(lastAbstractNumStyle_) then
				node := numberingXml_.FirstChildElement('w:numbering').InsertAfterChild(lastAbstractNumStyle_, o.Marshal());
			else
				node := numberingXml_.FirstChildElement('w:numbering').InsertFirstChild(o.Marshal());
			lastAbstractNumStyle_ := node;
			o := TOfficeObj('TNumStyle');
			o.Init(node);
			_addStyle(o);
			_setNsId(o);
			return o;
		End;
		return nil;
	End;

	//系统默认支持的项目编号样式
	Function AddDefaultStyle(Name);
	Begin
		xmlData := TOfficeTemplate('numbering/' + name + '.xml');
		if not ifString(xmlData) then 
			return nil;
		return AddStyleByInnerXml(xmlData);
	End;

	//map项目对象
	Function _addStyle(o);
	Begin
		if o.multiLevelType = 'singleLevel' and o.numFmt = 'bullet' then Begin
			lvlText := o.lvl.Value('lvlText');
			if lvlText then Begin
				str := encoderadixstr(lvlText,"", 0x40000000+16);
				bullet_[str] := o;
			End;
		End
		else if not ifObj(singleNumLevel_) and o.multiLevelType = 'singleLevel' and o.numFmt = 'decimal' then
			singleNumLevel_ := o;
		else if not ifObj(singleCNLevel_) and o.multiLevelType = 'singleLevel' and o.numFmt = 'chineseCounting' then
			singleCNLevel_ := o;
		else if not ifObj(multiNumLevel_) and o.multiLevelType = 'multilevel' and o.numFmt = 'decimal' then
			multiNumLevel_ := o;

		numStyleObjs_[o.abstractNumId] := o;
	End;
	
	//生成nsid随机数->转16进制
	Function _setNsId(o);
	Begin
		v := Integer(RandomRange(1000000000,2000000000));
		id := inttohex(v, 1);
		if hash_[id] then 
			return _setNsId(o);
		hash_[id] := 1;
		o.nsid := id;
		o.tmpl := id;
		arr := o.Marshal();
		class(TSXml).UpdateNode(o.node_, arr['attributes'], arr['children']);
	End;
private	
	docx_;
	numberingXml_;
	maxAbstractNumId_:integer;
	maxNumId_:integer;
	lastAbstractNumStyle_;
	numStyleObjs_;
	singleNumLevel_;
	singleCNLevel_;
	multiNumLevel_;
	bulletDefine_;
	bullet_;
	numIdMap_;
	hash_;
End;
