【问题标题】:How to parse this path-like string from SMO?如何从 SMO 解析这个类似路径的字符串?
【发布时间】:2012-08-21 06:46:02
【问题描述】:

我想知道,有没有标准的方法来解析这种类似路径的字符串:

Server[@Name='MyServerName']/Database[@Name='MyDatabaseName']/Table[@Name='MyTableName' and @Schema='MySchemaName']

结果必须是:

  • 项目名称(服务器)
    • PropertyName(名称)、PropertyValue(MyServerName)
  • 项目名称(数据库)
    • PropertyName(名称)、PropertyValue(MyDatabaseName)
  • 项目名称(表)
    • PropertyName(名称)、PropertyValue(MyTableName)
    • PropertyName(架构)、PropertyValue (MySchemaName)

这里最明显的是创建一个正则表达式(当然还有String.Split),但可能有更好的标准方法吗?

信息:字符串来自 SMO 的Urn.Value

更新。

答案找到了,见下文。

【问题讨论】:

  • 解析自定义字符串的标准方法? :)
  • 这看起来像XPath。您可能想查看 .NET 框架的 respective classes。除此之外,您必须提供自定义代码才能执行此操作,或者查看具有 xpath grammar 的 ANTLR(从未查看过它,YMMV)。
  • 如果你有办法解析这个 -> PropertyName (Schema), PropertyValue (MySchemaName) 那么你需要做的就是为你的结构的其余部分聚合/组合它。
  • @Default:我理解你的讽刺,但可能这个字符串有任何类型的众所周知的语法,我不知道?我不喜欢再发明一个轮子。
  • 结果是Dictionary<>还是XML?

标签: c#


【解决方案1】:

嗯,我做到了。 :)

答案很简单。有Urn.XPathExpression 属性。但它的返回值类型是Microsoft.SqlServer.Management.Sdk.Sfc.XPathExpression,而不是System.Xml.XPath.XPathExpression(这让我很困惑)。

来自 SMO 的 XPathExpression 具有解析自身所需的所有功能:

        var urn = new Urn("Server[@Name='MyServerName']/Database[@Name='MyDatabaseName']/Table[@Name='MyTableName' and @Schema='MySchemaName']");

        for (var i = 0; i < urn.XPathExpression.Length; i++)
        {
            Console.WriteLine("ItemName ({0})", urn.XPathExpression[i].Name);

            foreach (DictionaryEntry item in urn.XPathExpression[i].FixedProperties)
            {
                Console.WriteLine("\tPropertyName ({0}), PropertyValue ({1})", item.Key, item.Value);
            }
        }

产生这个输出:

ItemName (Server)
        PropertyName (Name), PropertyValue ('MyServerName')
ItemName (Database)
        PropertyName (Name), PropertyValue ('MyDatabaseName')
ItemName (Table)
        PropertyName (Name), PropertyValue ('MyTableName')
        PropertyName (Schema), PropertyValue ('MySchemaName')

Christian.K,感谢有关 XPath 的提示!

【讨论】:

    【解决方案2】:

    也许有点晚了,但我一直在寻找相同的答案,然后我自己偶然发现了这个。 Urn 有几个 Get 函数。

     var urn = new Urn("Server[@Name='MyServerName']/Database[@Name='MyDatabaseName']/Table[@Name='MyTableName' and @Schema='MySchemaName']");
        Console.WriteLine(urn.GetNameForType("Table"));
    

    将导致“MyTableName”

    【讨论】:

      【解决方案3】:

      没有要测试的代码应用,但类似

      var resultArr=str.Split(new char[]{'/', '[',']','@', '='}); 应该创建一个您想要的工件数组。

      剩下的唯一事情就是为它们中的每一个识别正确的数组索引

      【讨论】:

      • Tigran,感谢您的回答。我的问题必须更清楚:我想避免使用正则表达式和String.Split
      • @Denis:如果还没有做任何事情(它不是标准字符串),您需要编写一个小的 parser。但这听起来像这样的任务的繁琐解决方案,所以如果你没有真正不使用Split(..)或任何其他内置函数的严重理由,建议使用它们。
      • @alexn:如果你需要解析'host.domain.com/service?param1=value&param=2'的值,你会使用UriBuilder类吗?或者你会用String.Split解析它?这个字符串看起来像路径,或者xpath表达式……当然,如果不标准,我会用regex'es。
      • @Dennis 我会使用Uri.ParseString.Split / Regex 是解决此问题的简单轻量级解决方案。如果您只需要解析那个简单的字符串,那么使用 ANTLR 和 XPath 语法就太过分了。示例:gist.github.com/3413106.
      【解决方案4】:

      我相信,唯一的标准方法是使用正则表达式与模式匹配

      下面的代码 sn-p 会有所帮助 -

          string input = @"Server[@Name='MyServerName']/Database[@Name='MyDatabaseName']/Table[@Name='MyTableName' and @Schema='MySchemaName']";
          string elementPattern = @"(?<ItemName>\w+)\[@(?<PropertyName>\w+)='(?<PropertyValue>\w+)'( and @(?<PropertyName>\w+)='(?<PropertyValue>\w+)')*\]";
      
          Regex elementRegex = new Regex(elementPattern, RegexOptions.Compiled);
      
          string[] elements = input.Split('/');
      
          foreach (string element in elements)
          {
              Match m = elementRegex.Match(element);
      
              if (m.Success)
              {
                  Console.WriteLine("ItemName ({0})", m.Groups["ItemName"]);
      
                  foreach (Capture capture in m.Groups["PropertyName"].Captures)
                  {
                      Console.WriteLine("PropertyName ({0})", capture.Value);
                  }
      
                  foreach (Capture capture in m.Groups["PropertyValue"].Captures)
                  {
                      Console.WriteLine("PropertyValue ({0})", capture.Value);
                  }
              }
          }
      
          Console.ReadKey();
      

      输出:-

      ItemName (Server)
      PropertyName (Name)
      PropertyValue (MyServerName)
      ItemName (Database)
      PropertyName (Name)
      PropertyValue (MyDatabaseName)
      ItemName (Table)
      PropertyName (Name)
      PropertyName (Schema)
      PropertyValue (MyTableName)
      PropertyValue (MySchemaName)
      

      注意:请根据您的要求进行更改。

      【讨论】:

      • 谢谢,但“这里最明显的是做一个正则表达式”-引用我的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-24
      相关资源
      最近更新 更多