Мне пришлось получить что-то очень похожее, и я закончил тем, что использовал пользовательские поля "PlaceHolder" вместо полей Word (у них действительно есть различные ограничения, такие как - header, footer и body - все используют разные объекты).
В моем шаблоне слова я пометил PlaceHolder следующим образом - ## MyPlaceHolderName! #.Затем я проанализировал текст шаблона слова, чтобы найти все PlaceHolders, используя RegEx, и заменил их фактическими значениями формы InfoPath.
Единственным недостатком этого решения является то, что ваши поля PlaceHolders и ваши InfoPath должны иметь одинаковые имена, иначе вы не сможете выполнить какое-либо сопоставление.
Рассмотрите этот метод:
private void FillDocument(Stream documentStream, string xmlFields)
{
var doc = new XmlDocument();
doc.LoadXml(xmlFields);
var props = doc.SelectSingleNode("properties");
if (props == null) throw new Exception("No properties found.");
//transform the xml properties to dictionary for easier replacement
var fields = props.ChildNodes.Cast<XmlNode>().ToDictionary
(node => string.Format("##{0}!#", node.Name), node => node.InnerText);
using (var document = WordprocessingDocument.Open(documentStream, true))
{
var main = document.MainDocumentPart;
//replace the fields in the main document
main.Document.InnerXml = ReplaceFields(main.Document.InnerXml, fields);
//replace the fields in the headers
foreach (var headerPart in main.HeaderParts)
headerPart.Header.InnerXml = ReplaceFields(headerPart.Header.InnerXml, fields);
//replace the fields in the footers
foreach (var footerPart in main.FooterParts)
footerPart.Footer.InnerXml = ReplaceFields(footerPart.Footer.InnerXml, fields);
main.Document.Save();
}
}
private string ReplaceFields(string xmlPart, Dictionary<string, string> fields)
{
//searches the xml for the declared fields
var fieldRegex = new Regex("##[^#]*!#");
var matches = fieldRegex.Matches(xmlPart);
foreach (Match match in matches)
{
//the fields are within tags (InnerText) so remove all other xml stuff
var innerRegex = new Regex("<[^>]*>");
string fieldName = innerRegex.Replace(match.Groups[0].Value, "");
//replace the actual value of the field
if(fields.ContainsKey(fieldName))
xmlPart = xmlPart.Replace(match.Groups[0].Value, fields[fieldName]);
}
return xmlPart;
}
Вы бы использовали его следующим образом:
//open the file from as stream (in this example, the file is opened from SP
using (var stream = templateFile.OpenBinaryStream())
{
//iterate the properties you need and add them in this format
var xmlProperties = "<properties><MyPlaceHolderName>MyPlaceHolderValue</MyPlaceHolderName></properties>";
//fill out the fields
FillDocument(stream, xmlProperties);
}
Я знаю, что Xml-Replacing и xmlProperties относительно сумасшедшие, но я должен был реализовать это так из-за моих требований(метод вызывается WebService из InfoPath).Дайте мне знать, если вам понадобится дополнительная помощь.