dinghao

记录成长点滴

 

解析WordprocessingML(三)解析WordMl的基本方法和途径(b)-映射xsd

六、choicesequencemaxoccminocc的映射

简单的可以用List实现,复杂的必须自己写程序控制。

例子:CT_BodyEG_ContentBlockContent的映射方式,EG_ContentBlockContent包含了choicemaxocc

xsd:

1、               
精确映射,即实现一一映射。

下面的类实现Unbounded

    不足:调用者必须知道存在EG_ContentBlockContent组,而我希望所有组都对调用者透明。

public class U_EG_ContentBlockContent Content;

{

   public IList<EG_ContentBlockContent> Content;

}

   下面的类实现EG_ContentBlockContent
   
public class EG_ContentBlockContent: EG_RunLevelElts
    {
                     
        
#region customXml

        
private CT_CustomXmlBlock customXmlField;

        
/// <summary>
        
/// Block-Level Custom XML Element
        
///     - Required
        
/// </summary>
        public CT_CustomXmlBlock customXml
        {
            
get { return customXmlField; }
            
set { customXmlField = value; }
        }

        
#endregion // customXml

        
#region sdt

        
private CT_SdtBlock sdtField;

        
/// <summary>
        
/// Block-Level Structured Document Tag
        
///     - Required
        
/// </summary>
        public CT_SdtBlock sdt
        {
            
get { return sdtField; }
            
set { sdtField = value; }
        }
        
public CT_P[] Paragraphs;
        
public CT_Tbl[] Tbl;
        
#endregion // sdt
      
}

这种方式是最准确的映射,代价就是很难实现choice复杂,并且对调用者来说也不方便(这点可以用一个接口绕过,但是第一点确实很烦人)。

1、          不精确的xsd映射,xsd和类不存在一一对应关系。

仔细分析CT_Bodyxsd定义,根据定义xsd考虑所有可能产生的xml形式。让后用类包含所有形式。

       EG_ContentBlockContent包含四个元素和一个组,组可以用继承,四个元素中的两个也是unbounded,另外两个的maxocc1,由于EG_ContentBlockContent是作为unbounded引用的,所以四个元素实际上都是unbounded,他们在xml中可以以任意顺序出现n次。

       至此可以产生下面的映射方式:

public class EG_ContentBlockContent : EG_RunLevelElts
    {
        
#region customXml

         
/// <summary>
        
/// Block-Level Custom XML Element
        
///     - Required
        
/// </summary>
        public CT_CustomXmlBlock[] customXml
        {
            
get { //类似p}
          
        }

        
#endregion // customXml


        
/// <summary>
        
/// Block-Level Structured Document Tag
        
///     - Required
        
/// </summary>
        public CT_SdtBlock[] sdt
        {
            
get { //类似p }
            
        }

        
#endregion // sdt

        
#region Content

        
private System.Collections.Generic.List<IContent> content;

        
/// <summary>
        
/// The content of the body (to keep the order in the Paragraphs and Tables)
        
/// </summary>
        public System.Collections.Generic.List<IContent> Content
        {
            
get
            {
                
if (content == null)
                {
                    content 
= new System.Collections.Generic.List<IContent>();
                }
                
return content;
            }
        }

        
#endregion

        
#region p

        
/// <summary>
        
/// Paragraphs
        
///     - Not required
        
/// To Add a Table use the Content Property
        
/// </summary>
        public CT_P[] Paragraphs
        {
            
get
            {
                
if (content == null)
                {
                    
return new CT_P[0];
                }
                
else
                {
                    System.Collections.Generic.List
<CT_P> list = new System.Collections.Generic.List<CT_P>();
                    
foreach (IContent elts in content)
                    {
                        
if (elts is CT_P)
                        {
                            list.Add((CT_P)elts);
                        }
                    }
                    
return list.ToArray();
                }
            }
        }

        
#endregion // p

        
#region tbl


        
/// <summary>
        
/// Table
        
///     - Not required
        
/// To Add a Table use the Content Property
        
/// </summary>
        public CT_Tbl[] tbl
        {
            
get
            {
                
if (content == null)
                {
                    
return new CT_Tbl[0];
                }
                
else
                {
                    System.Collections.Generic.List
<CT_Tbl> list = new System.Collections.Generic.List<CT_Tbl>();
                    
foreach (IContent elts in content)
                    {
                        
if (elts is CT_Tbl)
                        {
                            list.Add((CT_Tbl)elts);
                        }
                    }
                    
return list.ToArray();
                }

            }
        }
}

这要求所有的组成员必须实现某个接口,在此用了IContent。这样定义Group,从本质上看已经不是xsdgroup了。在这个元素中这样处理简单,但是在别的元素中就不一定,它增加了问题的不确定性,或许后面都可以这样映射,也可能回出现大问题,不得不采用第一种方式,这样就又会把结构打乱,问题会变得更复杂,这也是为啥要尽可能的把类和xsd一一对应,如此一来,结构上有ms设计的xsd做参考,一切的变化都不会太离谱,ms改变xsd后,类库修改也小些。

3、最后看看WarstarDev.Office2k7的映射方式(错误的):

public class EG_ContentBlockContent : EG_RunLevelElts
    {
        
#region customXml

        
private CT_CustomXmlBlock customXmlField;

        
/// <summary>
        
/// Block-Level Custom XML Element
        
///     - Required
        
/// </summary>
        public CT_CustomXmlBlock customXml
        {
            
get { return customXmlField; }
            
set { customXmlField = value; }
        }

        
#endregion // customXml

        
#region sdt

        
private CT_SdtBlock sdtField;

        
/// <summary>
        
/// Block-Level Structured Document Tag
        
///     - Required
        
/// </summary>
        public CT_SdtBlock sdt
        {
            
get { return sdtField; }
            
set { sdtField = value; }
        }

        
#endregion // sdt

        
#region Content

        
private System.Collections.Generic.List<EG_RunLevelElts> content;

        
/// <summary>
        
/// The content of the body (to keep the order in the Paragraphs and Tables)
        
/// </summary>
        public System.Collections.Generic.List<EG_RunLevelElts> Content
        {
            
get
            {
                
if (content == null)
                {
                    content 
= new System.Collections.Generic.List<EG_RunLevelElts>();
                }
                
return content;
            }
        }

        
#endregion

        
#region p

        
/// <summary>
        
/// Paragraphs
        
///     - Not required
        
/// To Add a Table use the Content Property
        
/// </summary>
        public CT_P[] Paragraphs
        {
            
get
            {
                
if (content == null)
                {
                    
return new CT_P[0];
                }
                
else
                {
                    System.Collections.Generic.List
<CT_P> list = new System.Collections.Generic.List<CT_P>();
                    
foreach (EG_RunLevelElts elts in content)
                    {
                        
if (elts is CT_P)
                        {
                            list.Add((CT_P) elts);
                        }
                    }
                    
return list.ToArray();
                }
            }
        }

        
#endregion // p

        
#region tbl

    
        
/// <summary>
        
/// Table
        
///     - Not required
        
/// To Add a Table use the Content Property
        
/// </summary>
        public CT_Tbl[] tbl
        {
            
get
            {
                
if (content == null)
                {
                    
return new CT_Tbl[0];
                }
                
else
                {
                    System.Collections.Generic.List
<CT_Tbl> list = new System.Collections.Generic.List<CT_Tbl>();
                    
foreach (EG_RunLevelElts elts in content)
                    {
                        
if (elts is CT_Tbl)
                        {
                            list.Add((CT_Tbl) elts);
                        }
                    }
                    
return list.ToArray();
                }
              
            }
        }

        
#endregion // tbl
}

错误的地方是,它把我上面说的两种方式和在了一起(更像第二种),造成CT_CustomXmlBlockCT_SdtBlock没有实现unbounded,是个四不像的映射方式。其次他借用EG_RunLevelElts来管理Ilist元素,有点太取巧了(感觉不会是MS为程序映射xsd而故意设计的,但是整个EG_ContentBlockContent的元素都实现了EG_RunLevelElts,实在是巧合!!),在此可能简单写,但是对程序结构并没有好处。

两种方式各有优缺点,半斤八两,真不知道用哪种方式好些,第一种方式choice很难处理,我想到的只有在运行时做检测一种办法,希望有人能提出更好的解决方案。

第二种把choice绕过去了,但是他并不是xsd到类的一一映射,风险很大,很可能是灾难性的。

现在我采用的是另一种方式,但现在已经走到死路了,逻辑变的越来越复杂,必须改成这两种之一。目前比较倾向于第二种,第一种方式对调用者来说,把检测推到运行时几乎是不能忍受的,但又担心第二种会出现我现在碰到的情况,最终复杂到没有办法处理。

七、sequencechoice类似,就不说了。其他问题就是由于.net不支持多继承导致的,解决方式只能是在映射时做些调整,又是一个必须要仔细权衡的问题,弄不好也会把结构弄的特别乱。

总,想写一个最好的WordMl库,目前还赶不上WarstarDev.Office2k7,但是它用反射、XmlWriter解析的方式已经决定它的灵活性和功能都是有限的,再加上它在映射xsd方面的错误、它的结构也不太好,总会超过它的。

      WordMl实在是个超级复杂的东西,尤其是采用Dom解析方式时,我做到现在结构已经大调两次了,但是还必须再做一次大的调整才可能把结构稳定下来,到今天才算把wordml的结构弄清楚,入门了,希望这次调整是最后一次,两个月下来快被它弄死了。
   

解析WordprocessingML(一)查找和替换

http://www.cnblogs.com/bluewater/admin/EditPosts.aspx?postid=627710

解析WordprocessingML(二)通过数据集自动生成表格

http://www.cnblogs.com/bluewater/archive/2007/03/02/662040.html

解析WordprocessingML(三)解析WordMl的基本方法和途径(a

http://www.cnblogs.com/bluewater/archive/2007/03/02/661824.html

解析WordprocessingML(三)解析WordMl的基本方法和途径(b

http://www.cnblogs.com/bluewater/archive/2007/03/02/661885.html

解析WordprocessingML(四)转换到Html格式

Xsd入门

http://www.cnblogs.com/bluewater/archive/2007/03/02/661927.html


posted on 2007-03-04 19:13  思无邪  阅读(4298)  评论(4编辑  收藏  举报

导航