使用asp.net 4
我们在工作中做了很多Word合并。而不是使用Word的复杂条件语句我想嵌入我自己的语法。类似的东西:
Dear Mr. { select lastname from users where userid = 7 },
Your invoice for this quarter is: ${ select amount from invoices where userid = 7 }.
......
理想情况下,我希望将其变为:
string.Format("Dear Mr. {0}, Your invoice for this quarter is: ${1}", sqlEval[0], sqlEval[1]);
任何想法?
答案 0 :(得分:0)
嗯,我真的不建议为此推出自己的解决方案,但我会按照要求回答问题。
首先,您需要处理文本并提取SQL语句。为此你需要一个简单的解析器:
/// <summary>Parses the input string and extracts a unique list of all placeholders.</summary>
/// <remarks>
/// This method does not handle escaping of delimiters
/// </remarks>
public static IList<string> Parse(string input)
{
const char placeholderDelimStart = '{';
const char placeholderDelimEnd = '}';
var characters = input.ToCharArray();
var placeHolders = new List<string>();
string currentPlaceHolder = string.Empty;
bool inPlaceHolder = false;
for (int i = 0; i < characters.Length; i++)
{
var currentChar = characters[i];
// Start of a placeholder
if (!inPlaceHolder && currentChar == placeholderDelimStart)
{
currentPlaceHolder = string.Empty;
inPlaceHolder = true;
continue;
}
// Start of a placeholder when we already have one
if (inPlaceHolder && currentChar == placeholderDelimStart)
throw new InvalidOperationException("Unexpected character detected at position " + i);
// We found the end marker while in a placeholder - we're done with this placeholder
if (inPlaceHolder && currentChar == placeholderDelimEnd)
{
if (!placeHolders.Contains(currentPlaceHolder))
placeHolders.Add(currentPlaceHolder);
inPlaceHolder = false;
continue;
}
// End of a placeholder with no matching start
if (!inPlaceHolder && currentChar == placeholderDelimEnd)
throw new InvalidOperationException("Unexpected character detected at position " + i);
if (inPlaceHolder)
currentPlaceHolder += currentChar;
}
return placeHolders;
}
好的,这样就可以获得从输入文本中提取的SQL语句列表。您可能希望调整它以使用正确类型的解析器异常和一些输入保护(为了清楚起见,我省略了)。
现在您只需要将这些占位符替换为已评估的SQL的结果:
// Sample input
var input = "Hello Mr. {select firstname from users where userid=7}";
string output = input;
var extractedStatements = Parse(input);
foreach (var statement in extractedStatements)
{
// Execute the SQL statement
var result = Evaluate(statement);
// Update the output with the result of the SQL statement
output = output.Replace("{" + statement + "}", result);
}
这显然不是最有效的方法,但我认为它足以证明这个概念而不会使水变得混乱。
您需要定义Evaluate(string)
方法。这将处理执行SQL。
答案 1 :(得分:0)
我刚刚在这里为一家律师事务所完成了这样的专有解决方案。 我评估了一款名为Windward的产品报告。这有点贵,特别是如果你需要大量的副本,但是对于一个用户来说它并不坏。
它可以从XML或SQL数据源中提取(如果我记得的话,还可以更多)。
可能值得一看(不,我不为他们工作,只评估他们的东西)
答案 2 :(得分:0)
您可能想要查看codeplex上的剃须刀引擎项目
http://razorengine.codeplex.com/
在模板中使用SQL等看起来不错。我建议你为每个模板制作一个ViewModel。
Razor的东西真的很容易使用。只需添加一个引用,导入命名空间,然后像这样调用Parse方法:
(VB家伙原谅语法!)
MyViewModel myModel = new MyViewModel("Bob",150.00); //set properties
string myTemplate = "Dear Mr. @Model.FirstName, Your invoice for this quarter is: @Model.InvoiceAmount";
string myOutput = Razor.Parse(myTemplate, myModel);
你的字符串可以来自任何地方 - 我使用存储在数据库中的模板,你可以从文件或其他任何地方加载它。它作为视图引擎非常强大,你可以做有条件的东西,循环等等。
答案 3 :(得分:0)
我最终推出了自己的解决方案,但谢谢。我真的不喜欢陈述。我需要重构它们。这是:
var mailingMergeString = new MailingMergeString(input);
var output = mailingMergeString.ParseMailingMergeString();
public class MailingMergeString
{
private string _input;
public MailingMergeString(string input)
{
_input = input;
}
public string ParseMailingMergeString()
{
IList<SqlReplaceCommand> sqlCommands = new List<SqlReplaceCommand>();
var i = 0;
const string openBrace = "{";
const string closeBrace = "}";
while (string.IsNullOrWhiteSpace(_input) == false)
{
var sqlReplaceCommand = new SqlReplaceCommand();
var open = _input.IndexOf(openBrace) + 1;
var close = _input.IndexOf(closeBrace);
var length = close != -1 ? close - open : _input.Length;
var newInput = _input.Substring(close + 1);
var nextClose = newInput.Contains(openBrace) ? newInput.IndexOf(openBrace) : newInput.Length;
if (i == 0 && open > 0)
{
sqlReplaceCommand.Text = _input.Substring(0, open - 1);
_input = _input.Substring(open - 1);
}
else
{
sqlReplaceCommand.Command = _input.Substring(open, length);
sqlReplaceCommand.PlaceHolder = openBrace + i + closeBrace;
sqlReplaceCommand.Text = _input.Substring(close + 1, nextClose);
sqlReplaceCommand.NewInput = _input.Substring(close + 1);
_input = newInput.Contains(openBrace) ? sqlReplaceCommand.NewInput : string.Empty;
}
sqlCommands.Add(sqlReplaceCommand);
i++;
}
return sqlCommands.GetParsedString();
}
internal class SqlReplaceCommand
{
public string Command { get; set; }
public string SqlResult { get; set; }
public string PlaceHolder { get; set; }
public string Text { get; set; }
protected internal string NewInput { get; set; }
}
}
internal static class SqlReplaceExtensions
{
public static string GetParsedString(this IEnumerable<MailingMergeString.SqlReplaceCommand> sqlCommands)
{
return sqlCommands.Aggregate("", (current, replaceCommand) => current + (replaceCommand.PlaceHolder + replaceCommand.Text));
}
}