如何使用razor(在Umbraco中)拆分文本字符串?

时间:2011-11-24 17:26:50

标签: asp.net razor split umbraco

我对剃刀世界相对(更完全)是新手,并且不可避免地遇到了我的第一道障碍。我是一名Web开发人员,也是CMS Umbraco的新手,因此我一直在使用razor进行脚本编写。

我的问题相当简单;如何分割文本字符串以显示4个不同的单词/值,中间是逗号?

理想情况下,我想转向:

“为什么,不要,这,工作”的“为什么不要这个工作”,并且可能使事情变得复杂:“'为什么',不要,这个,工作”(用's围绕第一个词')

我一直尝试从另一个线程使用此方法,但无济于事:

@foreach (string s in "1,2,3".Split(',')) {
  @: s is equal to @s<br/>
}

尝试将此语法实现到我自己的脚本中,它看起来如下所示,因此它不起作用:

@inherits umbraco.MacroEngines.DynamicNodeContext
@{
    foreach (var x in Model.uctextstring.Split(',')) {
        @x.InnerText
    }
}

1 个答案:

答案 0 :(得分:2)

这并不是Razor特别要解决的问题。我认为这样做的最好方法是使用专用方法。简单的拆分不会做你想要的,因为你不知道要拆分的逻辑点,我也想不出一个简单的Regex解决方案。所以这是一个非常基本的例子,逐个字符地移动字符串来识别基本的单词边界:

public static IEnumerable<string> SplitString(string value)
{
  char last = char.MinValue;
  bool inWord = false;
  string word = string.Empty;

  foreach (char c in s)
  {
      if (char.IsLetter(c))
      {
          // Covers situations with apostrophised characters, e.g. 's
          if (last == '\'' && char.IsLetter(c) && inWord)
          {
              word += last;
              word += c;
              yield return word;

              word = string.Empty;
              inWord = false;
          }
          else if (char.IsUpper(c) && !inWord)
          {
              // Start of a new word.
              word += c;
              inWord = true;
          } 
          else if (char.IsUpper(c))
          {
              // Return the last word.
              yield return word;

              // Start a new string.
              word = string.Empty + c;
              inWord = true;
          }
          else
          {
              // Append to the current string.
              word += c;
          }
      } 
      else
      {
          if (c == '\'' && inWord)
          {
              // If we are at an apostrophe, set and then skip
              last = c;
              continue;
          }

          if (word.Length > 0)
          {
              // Otherwise, if we have a previous word, return.
              yield return word;

              // Clear ready for the next word.
              word = string.Empty;
              inWord = false;
          }
      }

      last = c;
  }

  // If there is one more remaining word, return it.
  if (word.Length > 0)
      yield return word;
}

您可以使用

加入/连接
string result = string.Join(", ", SplitString(sentence));

当我们使用yield时,此方法利用编译器创建状态机的能力。这很好,因为我们可以枚举字符流,并在实际获取结果时返回结果。

现在,这不会直接在Razor模板中工作,因为您需要声明模板方法。这样做的脏方法是使用Func<string, IEnumerable<string>>实例声明一个函数:

@{
    Func<string, IEnumerable<string>> splitter = s =>
    {
      char last = char.MinValue;
      bool inWord = false;
      string word = string.Empty;

      IList<string> words = new List<string>();

      foreach (char c in s)
      {
          if (char.IsLetter(c))
          {
              if (last == '\'' && char.IsLetter(c) && inWord)
              {
                  word += last;
                  word += c;
                  words.Add(word);

                  word = string.Empty;
                  inWord = false;
              }
              else if (char.IsUpper(c) && !inWord)
              {
                  word += c;
                  inWord = true;
              } 
              else if (char.IsUpper(c))
              {
                  words.Add(word);

                  word = string.Empty + c;
                  inWord = true;
              }
              else
              {
                  word += c;
              }
          } 
          else
          {
              if (c == '\'' && inWord)
              {
                  last = c;
                  continue;
              }

              if (word.Length > 0)
              {
                  words.Add(word);

                  word = string.Empty;
                  inWord = false;
              }
          }

          last = c;
      }

      if (word.Length > 0)
        words.Add(word);

      return words;
    };
  }

但即便如此也不是很好。它也不是正确分割字符串的防弹方式。