3

我目前正在开发 Silverlight 应用程序,需要将 XML 数据转换为适当的对象以进行数据绑定。本次讨论的基本类定义是:

public class TabularEntry
    {
        public string Tag { get; set; }
        public string Description { get; set; }
        public string Code { get; set; }
        public string UseNote { get; set; }
        public List<string> Excludes { get; set; }
        public List<string> Includes { get; set; }
        public List<string> Synonyms { get; set; }
        public string Flags { get; set; }
        public List<TabularEntry> SubEntries { get; set; }
    }

以下是可能用于提供此对象的 XML 示例:

<I4 Ref="1">222.2
    <DX>Prostate</DX>
    <EX>
        <I>adenomatous hyperplasia of prostate (600.20-600.21)</I>
        <I>prostatic:
            <I>adenoma (600.20-600.21)</I>
            <I>enlargement (600.00-600.01)</I>
            <I>hypertrophy (600.00-600.01)</I>
        </I>
    </EX>
    <FL>M</FL>
</I4>

因此,各种节点映射到特定属性。这个问题的关键是<EX><I>节点。节点将<EX>包含一个或多个<I>节点的集合,并且在此示例中匹配上述类定义中的“排除”属性。

挑战来了(对我来说)。我无法控制发出此 XML 的 Web 服务,因此无法更改它。您会注意到,在此示例中,一个<I>节点还包含一个或多个<I>节点的另一个集合。我希望我可以使用 LINQ to XML 查询,它允许我将两个级别合并到一个集合中,并使用一个字符来分隔较低级别的项目,所以在这个例子中,当 LINQ 查询返回一个 TablularEntry对象,它将包含如下所示的排除项的集合:

  • 前列腺腺瘤性增生(600.20-600.21)
  • 前列腺:
  • *腺瘤 (600.20-600.21)
  • *放大 (600.00-600.01)
  • *肥大(600.00-600.01)

因此,在 XML 中,最后 3 个条目实际上是第二个条目的子对象,但在对象的 Excludes 属性中,它们都是同一个集合的一部分,前三个子对象包含标识符字符/字符串。

我有我在下面使用的 LINQ 查询的开始,我无法完全弄清楚将为我整合子对象的位。现在存在的代码是:

List<TabularEntry> GetTabularEntries(XElement source)
        {
            List<TabularEntry> result;

            result = (from tabularentry in source.Elements()
                         select new TabularEntry()
                         {
                             Tag = tabularentry.Name.ToString(),
                             Description = tabularentry.Element("DX").ToString(),
                             Code = tabularentry.FirstNode.ToString(),
                             UseNote = tabularentry.Element("UN") == null ? null : tabularentry.Element("UN").Value,
                             Excludes = (from i in tabularentry.Element("EX").Elements("I")
                                             select i.Value).ToList()
                         }).ToList();

            return result;
        }

我在想我需要在里面嵌套一个 FROM 语句

排除=(来自我...)

声明收集子节点,但不能完全完成。当然,这可能是因为我的逻辑有点混乱。

如果您需要更多信息来回答,请随时提问。

提前致谢,

史蒂夫

4

2 回答 2

2

试试这个:

    List<TabularEntry> GetTabularEntries(XElement source)
    {
        List<TabularEntry> result;

        result = (from tabularentry in source.Elements()
                  select new TabularEntry()
                  {
                      Tag = tabularentry.Name.ToString(),
                      Description = tabularentry.Element("DX").ToString(),
                      Code = tabularentry.FirstNode.ToString(),
                      UseNote = tabularentry.Element("UN") == null ? null : tabularentry.Element("UN").Value,
                      Excludes = (from i in tabularentry.Element("EX").Descendants("I")
                                  select (i.Parent.Name == "I" ? "*" + i.Value : i.Value)).ToList()

                  }).ToList();

        return result;
    }

(编辑)

如果您需要“I”的当前嵌套级别,您可以执行以下操作:

    List<TabularEntry> GetTabularEntries(XElement source)
    {
        List<TabularEntry> result;

        result = (from tabularentry in source.Elements()
                  select new TabularEntry()
                  {
                      Tag = tabularentry.Name.ToString(),
                      Description = tabularentry.Element("DX").ToString(),
                      Code = tabularentry.FirstNode.ToString(),
                      UseNote = tabularentry.Element("UN") == null ? null : tabularentry.Element("UN").Value,
                      Excludes = (from i in tabularentry.Element("EX").Descendants("I")
                                  select (ElementWithPrefix(i, '*'))).ToList()

                  }).ToList();

        return result;
    }

    string ElementWithPrefix(XElement element, char c)
    {
        string prefix = "";
        for (XElement e = element.Parent; e.Name == "I"; e = e.Parent)
        {
            prefix += c;
        }
        return prefix + ExtractTextValue(element);
    }

    string ExtractTextValue(XElement element)
    {
        if (element.HasElements)
        {
            return element.Value.Split(new[] { '\n' })[0].Trim();
        }
        else
            return element.Value.Trim();
    }

输入:

<EX>
    <I>adenomatous hyperplasia of prostate (600.20-600.21)</I>
    <I>prostatic:
        <I>adenoma (600.20-600.21)</I>
        <I>enlargement (600.00-600.01)</I>
        <I>hypertrophy (600.00-600.01)
            <I>Bla1</I>
            <I>Bla2
                <I>BlaBla1</I>
            </I>
            <I>Bla3</I>
        </I>
            </I>
</EX>

结果:

* adenomatous hyperplasia of prostate (600.20-600.21)
* prostatic:
* *adenoma (600.20-600.21)
* *enlargement (600.00-600.01)
* *hypertrophy (600.00-600.01)
* **Bla1
* **Bla2
* ***BlaBla1
* **Bla3
于 2009-02-02T19:13:05.540 回答
0

后代会得到你所有的I孩子。这FirstNode将有助于将 的prostatic:价值与其子项的价值区分开来。的值中有一个返回字符prostatic:,我用Trim.

XElement x = XElement.Parse(@"
<EX>
  <I>adenomatous hyperplasia of prostate (600.20-600.21)</I>
  <I>prostatic:
    <I>adenoma (600.20-600.21)</I>
    <I>enlargement (600.00-600.01)</I>
    <I>hypertrophy (600.00-600.01)</I>
  </I>
</EX>");
//
List<string> result = x
  .Descendants(@"I")
  .Select(i => i.FirstNode.ToString().Trim())
  .ToList();

这是获取这些星号的一种hacky方法。我没有时间改进它。

List<string> result2 = x
  .Descendants(@"I")
  .Select(i =>
    new string(Enumerable.Repeat('*', i.Ancestors(@"I").Count()).ToArray())
    + i.FirstNode.ToString().Trim())
  .ToList();
于 2009-02-02T19:07:08.453 回答