解析WordprocessingML(一)查找和替换

时间:2022-08-02 06:26:23

替换文本,在平时很简单的问题,如果通过wordProcessingML操作,可能就变成word操作中最复杂的问题了。

因为字体、拼写检测等细微的差别,word中在一起的字符串,转到xml时有可能会封装到几个<w:r>中。这就给替换带来很大难度,使原本简单的问题变的复杂。

如:[pr:test/]有可能会被分解到三个<w:r>,还可能更多。最多会分散到n!个<w:r>,n是标记包含的字符数。

这就给找到匹配增加了难度,也很难保留原来的word格式。
   为了实现Doc的随机读写,只能用xpath,下面是[pr:test/]在word xml中的一种情况

解析WordprocessingML(一)查找和替换< w:r >
解析WordprocessingML(一)查找和替换        
< w:rPr >
解析WordprocessingML(一)查找和替换            
< w:rFonts  w:ascii ="新宋体"  w:fareast ="新宋体" />
解析WordprocessingML(一)查找和替换            
< wx:font  wx:val ="新宋体"  xmlns:wx ="http://schemas.microsoft.com/office/word/2003/auxHint" />
解析WordprocessingML(一)查找和替换            
< w:noProof />
解析WordprocessingML(一)查找和替换            
< w:color  w:val ="A31515" />
解析WordprocessingML(一)查找和替换            
< w:kern  w:val ="0" />
解析WordprocessingML(一)查找和替换            
< w:sz  w:val ="18" />
解析WordprocessingML(一)查找和替换            
< w:sz-cs  w:val ="18" />
解析WordprocessingML(一)查找和替换        
</ w:rPr >
解析WordprocessingML(一)查找和替换        
< w:t > [pr </ w:t >
解析WordprocessingML(一)查找和替换    
</ w:r >
解析WordprocessingML(一)查找和替换    
< w:r >
解析WordprocessingML(一)查找和替换        
< w:rPr >
解析WordprocessingML(一)查找和替换            
< w:rFonts  w:ascii ="新宋体"  w:fareast ="新宋体"  w:hint ="fareast" />
解析WordprocessingML(一)查找和替换            
< wx:font  wx:val ="新宋体"  xmlns:wx ="http://schemas.microsoft.com/office/word/2003/auxHint" />
解析WordprocessingML(一)查找和替换            
< w:noProof />
解析WordprocessingML(一)查找和替换            
< w:color  w:val ="A31515" />
解析WordprocessingML(一)查找和替换            
< w:kern  w:val ="0" />
解析WordprocessingML(一)查找和替换            
< w:sz  w:val ="18" />
解析WordprocessingML(一)查找和替换            
< w:sz-cs  w:val ="18" />
解析WordprocessingML(一)查找和替换        
</ w:rPr >
解析WordprocessingML(一)查找和替换        
< w:t > : </ w:t >
解析WordprocessingML(一)查找和替换    
</ w:r >
解析WordprocessingML(一)查找和替换    
< w:r >
解析WordprocessingML(一)查找和替换        
< w:rPr >
解析WordprocessingML(一)查找和替换            
< w:rFonts  w:ascii ="新宋体"  w:fareast ="新宋体" />
解析WordprocessingML(一)查找和替换            
< wx:font  wx:val ="新宋体"  xmlns:wx ="http://schemas.microsoft.com/office/word/2003/auxHint" />
解析WordprocessingML(一)查找和替换            
< w:noProof />
解析WordprocessingML(一)查找和替换            
< w:color  w:val ="A31515" />
解析WordprocessingML(一)查找和替换            
< w:kern  w:val ="0" />
解析WordprocessingML(一)查找和替换            
< w:sz  w:val ="18" />
解析WordprocessingML(一)查找和替换            
< w:sz-cs  w:val ="18" />
解析WordprocessingML(一)查找和替换        
</ w:rPr >
解析WordprocessingML(一)查找和替换        
< w:t > test/] </ w:t >
解析WordprocessingML(一)查找和替换    
</ w:r >
解析WordprocessingML(一)查找和替换

 

我到目前想到了三种解决方案:

第一种最快,但是他只能解决标记位于一个<w:r>中的情况:

解析WordprocessingML(一)查找和替换public   string  ReplaceMarker(MarkerValueCollection mvc, bool  isVerify)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换        
{
解析WordprocessingML(一)查找和替换            _mvc 
= mvc;
解析WordprocessingML(一)查找和替换            
string[] marker = mvc.AllKeys;
解析WordprocessingML(一)查找和替换            
if (isVerify)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换                VerifyMarker(marker);
解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换            
string text = _wordParser.WordDoc.InnerXml;
解析WordprocessingML(一)查找和替换            MatchEvaluator me 
= new MatchEvaluator(ReplaceText);
解析WordprocessingML(一)查找和替换            
string newtext = Regex.Replace(text, _findMarker, me);
解析WordprocessingML(一)查找和替换            
return newtext;
解析WordprocessingML(一)查找和替换 
解析WordprocessingML(一)查找和替换        }

解析WordprocessingML(一)查找和替换       
解析WordprocessingML(一)查找和替换        
private   string  ReplaceText(Match m)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换        
{
解析WordprocessingML(一)查找和替换           
解析WordprocessingML(一)查找和替换            
if (_mvc.Get(new CommonMarker(m.ToString())) == null)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换                
return m.ToString();
解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换            
else
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换                
return _mvc.Get(new CommonMarker(m.ToString()));
解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换        }

解析WordprocessingML(一)查找和替换
 

因为假设标记位于是连续的,所以把xml当作纯文本,用正则表达式替换就可以了。
   第二中方案,可以解决段落中含有[],[/],[[pr:test/]/]的情况,标记中的个字符可以分散到任意个<w:r>,但是要求段中不能包含不匹配的[]

解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换 /// <summary>
解析WordprocessingML(一)查找和替换        
/// 替换给定段落中的值一次
解析WordprocessingML(一)查找和替换        
/// </summary>
解析WordprocessingML(一)查找和替换        
/// <param name="paragraph">段落节点</param>
解析WordprocessingML(一)查找和替换        
/// <param name="marker">标记</param>
解析WordprocessingML(一)查找和替换        
/// <param name="value">替换的值</param>
解析WordprocessingML(一)查找和替换        
/// <returns></returns>
解析WordprocessingML(一)查找和替换        
///<remarks>标记的begin,end不能有不匹配。</remarks>

解析WordprocessingML(一)查找和替换         private  XmlNode ReplaceMarkerOnce(XmlNode paragraph,  string  marker,  string  value)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换        
{
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换            CommonMarker cmarker 
= new CommonMarker(marker);
解析WordprocessingML(一)查找和替换            XmlNodeList wrs 
= ((XmlElement)paragraph).GetElementsByTagName("w:r");
解析WordprocessingML(一)查找和替换            
for (int i = 0; i < wrs.Count; i++)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换                
if (wrs[i].InnerText.IndexOf(marker) >= 0)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                
{
解析WordprocessingML(一)查找和替换                    wrs[i].InnerXml 
= string.Format(@"<w:t>{0}</w:t>", wrs[i].InnerText.Replace(marker, value));
解析WordprocessingML(一)查找和替换                }

解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换            IList
<int> begins = new List<int>();
解析WordprocessingML(一)查找和替换            IList
<int> ends = new List<int>();
解析WordprocessingML(一)查找和替换            
for (int i = 0; i < wrs.Count; i++)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换                
if (wrs[i].InnerText.IndexOf(cmarker.Begin) >= 0)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                
{
解析WordprocessingML(一)查找和替换                    begins.Add(i);
解析WordprocessingML(一)查找和替换                }

解析WordprocessingML(一)查找和替换                
if (wrs[i].InnerText.IndexOf(cmarker.End) >= 0)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                
{
解析WordprocessingML(一)查找和替换                    ends.Add(i);
解析WordprocessingML(一)查找和替换                }

解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换            
if (begins.Count != ends.Count)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换                
throw new ApplicationException("段落中有不匹配的标记");
解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换            
else
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                
for (int i = 0; i < begins.Count; i++)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                
{
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                    
string t = "";
解析WordprocessingML(一)查找和替换                    Stack
<XmlNode> rs = new Stack<XmlNode>();
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                    
for (int j = begins[i]; j <= ends[i]; j++)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                    
{
解析WordprocessingML(一)查找和替换                        rs.Push(wrs[j]);
解析WordprocessingML(一)查找和替换                        t 
= t + wrs[j].InnerText;
解析WordprocessingML(一)查找和替换                    }

解析WordprocessingML(一)查找和替换                    
if (t.IndexOf(cmarker.ToString()) >= 0)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                    
{
解析WordprocessingML(一)查找和替换                        XmlNode xn 
= rs.Pop();//把最后一个r保留
解析WordprocessingML(一)查找和替换                        
//替换
解析WordprocessingML(一)查找和替换
                        xn.InnerXml = string.Format(@"<w:t>{0}</w:t>", t.Replace(cmarker.ToString(), value));
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                        
while (rs.Count > 0)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                        
{
解析WordprocessingML(一)查找和替换                            XmlNode r 
= rs.Pop(); //移出的r
解析WordprocessingML(一)查找和替换
                            paragraph.RemoveChild(r);
解析WordprocessingML(一)查找和替换                        }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                        
return paragraph;
解析WordprocessingML(一)查找和替换                    }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                }

解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换            
return paragraph;
解析WordprocessingML(一)查找和替换        }

解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换
/// <summary>
解析WordprocessingML(一)查找和替换        
/// 替换给定段落中的标记
解析WordprocessingML(一)查找和替换        
/// </summary>
解析WordprocessingML(一)查找和替换        
/// <param name="paragraph">段落节点</param>
解析WordprocessingML(一)查找和替换        
/// <param name="marker">标记</param>
解析WordprocessingML(一)查找和替换        
/// <param name="value">替换的值</param>
解析WordprocessingML(一)查找和替换        
/// <returns></returns>
解析WordprocessingML(一)查找和替换        
///<remarks>标记的begin,end不能有不匹配。</remarks>

解析WordprocessingML(一)查找和替换   public  XmlNode ReplaceMarker(XmlNode paragraph,  string  marker,  string  value)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换        
{
解析WordprocessingML(一)查找和替换            CommonMarker cmarker 
= new CommonMarker(marker);
解析WordprocessingML(一)查找和替换            
string x = paragraph.InnerText;
解析WordprocessingML(一)查找和替换            
int count = Regex.Matches(x, cmarker.Reg).Count;
解析WordprocessingML(一)查找和替换            XmlNode xn 
= paragraph;
解析WordprocessingML(一)查找和替换            
for (int i = 0; i < count; i++)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换                replce(xn, marker, value);
解析WordprocessingML(一)查找和替换                xn 
= ReplaceMarkerOnce(xn, cmarker.ToString(), value);
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换          
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换        }

解析WordprocessingML(一)查找和替换

   思路是:一次仅替换一个标记一次。因为假定标记成对出现,可以根据其实标记的位置,把属于同一个标记的各个<w:r>节点入栈,并且只保留栈顶的节点,把其他节点的值放到栈顶节点,删除其他节点。这样就把标记规范化了,即把分散到多个的<w:r>的标记合并到一个<w:r>

   第三种解决方案,目前似乎可以解决上面所有的问题。在包含“大幅度d[][[pr:test/]sfsad[][[pr:test1/]/][[pr:test/] test1dfdfd的的[pr:tesdfd1/]”的word文本中可以正确识别标记。

解析WordprocessingML(一)查找和替换  public  XmlNode ReplaceMarker(XmlNode paragraph, CommonMarker cmarker,  string  value)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换        
{
解析WordprocessingML(一)查找和替换            
解析WordprocessingML(一)查找和替换            XmlNodeList wts 
= ((XmlElement)paragraph).GetElementsByTagName("w:t");
解析WordprocessingML(一)查找和替换            
//校验
解析WordprocessingML(一)查找和替换
            Stack<XmlNode> xn = new Stack<XmlNode>();
解析WordprocessingML(一)查找和替换            
foreach (XmlNode wt in wts)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换            
{
解析WordprocessingML(一)查找和替换                
string t = wt.InnerText;
解析WordprocessingML(一)查找和替换                
if (t.IndexOf(cmarker.ToString()) >= 0)//不用调整
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换
                {
解析WordprocessingML(一)查找和替换                    wt.InnerText 
= t.Replace(cmarker.ToString(), value);
解析WordprocessingML(一)查找和替换                    
break;
解析WordprocessingML(一)查找和替换                }

解析WordprocessingML(一)查找和替换                
bool isAdd = false;
解析WordprocessingML(一)查找和替换                
for (int i = 0; i < t.Length; i++)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                
{
解析WordprocessingML(一)查找和替换                    
if (t[i] == cmarker.begin[0])
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                    
{
解析WordprocessingML(一)查找和替换                        xn.Clear();
解析WordprocessingML(一)查找和替换                        xn.Push(wt);
解析WordprocessingML(一)查找和替换                        isAdd 
= true;//                      
解析WordprocessingML(一)查找和替换

解析WordprocessingML(一)查找和替换                    }

解析WordprocessingML(一)查找和替换                    
else if (t[i] == cmarker.end[1&& t[i - 1== cmarker.end[0])
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                    
{
解析WordprocessingML(一)查找和替换                        
string mk = "";
解析WordprocessingML(一)查找和替换                        
foreach (XmlNode xt in xn)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                        
{
解析WordprocessingML(一)查找和替换                            mk 
= xt.InnerText + mk;
解析WordprocessingML(一)查找和替换                        }

解析WordprocessingML(一)查找和替换                        
if (mk.IndexOf(cmarker.ToString()) >= 0)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                        
{
解析WordprocessingML(一)查找和替换                            xn.Pop().InnerText 
= mk.Replace(cmarker.ToString(), value);
解析WordprocessingML(一)查找和替换                            
//处理栈内容,清空栈
解析WordprocessingML(一)查找和替换
                            while (xn.Count > 0)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                            
{
解析WordprocessingML(一)查找和替换                                XmlNode xr 
= xn.Pop().ParentNode; //wr
解析WordprocessingML(一)查找和替换
                                XmlNode pa = xr.ParentNode;
解析WordprocessingML(一)查找和替换                                pa.RemoveChild(xr);
解析WordprocessingML(一)查找和替换                            }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                        }

解析WordprocessingML(一)查找和替换                        
//包含[/]但是不匹配此标记,跳过
解析WordprocessingML(一)查找和替换
                    }

解析WordprocessingML(一)查找和替换                    
else
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                    
{
解析WordprocessingML(一)查找和替换                        
if (xn.Count != 0)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                        
{
解析WordprocessingML(一)查找和替换                            
if (!isAdd)
解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换                            
{
解析WordprocessingML(一)查找和替换                                xn.Push(wt);
解析WordprocessingML(一)查找和替换                                isAdd 
= true;
解析WordprocessingML(一)查找和替换                            }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                        }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换                    }

解析WordprocessingML(一)查找和替换                }

解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换            }

解析WordprocessingML(一)查找和替换            
return paragraph;
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换
解析WordprocessingML(一)查找和替换        }
 
解析WordprocessingML(一)查找和替换
   

思路:思路和第二中类似,都是先规范标记,把分散到多个的<w:r>的标记合并到一个<w:r>。不同的是对包含标记的段落执行逐字符匹配,如果匹配开始标记,则入栈,碰到结束标记则出栈,解析栈中的节点。

调整后的xml是:

  

解析WordprocessingML(一)查找和替换解析WordprocessingML(一)查找和替换

 

 

替换中出现的难点是:

1   尽可能的保留word格式,如果只保留段格式,第一中方案就可以了,后两种只是为了尽可能保留段内文本的word格式,单仍有破坏(这是不可能避免的,最小化的破坏格式)。

2  word中抽出的节点,被修改后还能放到原来的位置,这就使功能强大的正则很难使用。

总:第三种是比较好的解决替换的方法,不知道大家还有什么好思路?我已经为它头疼两周了,一直找不到更好的算法。
第三种方法是刚想到的,我现在觉的还行,有人有更好的解决方式,一定要留言啊

 

解析WordprocessingML(一)查找和替换

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

解析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格式