通过递归使用 XElement 动态构建 Xml

2024-02-10

我是 linq to Xml 的新手。
我有一个递归方法作为参数XElement root它应该以表示给定递归深度的相关子树根的方式保存 XML 数据。

void recursiveMethod(XElement root);
更具体地说,还可以看看这个 XML 示例:

<start>
      <Class>
           <Worker>
                <Name> Dan </Name>
                <Phone> 123 </Phone> 
                <Class>
                      <Address>
                           <Street> yellow brick road </Street>
                           <Zip Code> 123456 </Zip Code>
                      </Address>
                </Class>
            </Worker>
      </Class>
...
</start>    

正如你可以想象的那样,Name是值类型,而Address是一个类参考。
Xml 信息应通过反射动态添加(采用自上而下的方法)。

长话短说,想象一下我正在调查Worker班级及达到Address类并想要“向下钻取”,所以我想使用当前 Worker 类的子节点的正确引用作为新的 XElement 根来调用我的递归方法,这样我将能够向其中添加我通过反射找到的内容这Address下面的一级递归深度。

请注意,此引用应该是 XElement 类型。

我怎样才能做到这一点?

EDIT:如果您有其他想法做所有这些事情但不与XElement我也很高兴听到,尽管我更喜欢XElement范围。

另一个问题:
我已经开始以一种天真的方式实现它,比如迭代所有字段(FieldInfo[] 的变量),如果我遇到了值类型(IsValueType),我会做类似的事情

 root.Add(new XElement("Field",
                      new XElement("Type", ...),
                      new XElement("Variable Name", ...),
                      new XElement("Value", ...)));     

因此,仅作为一般知识:
1.有没有办法只获取节点对其后代的引用,以便在较低的递归级别中我可以像上面那样执行另一个 root.Add(...) ,但此根将是对前一个根的孩子? (这意味着无需 Linq 语法即可完成整个操作)

2.我已经设法通过反射获取私有字段值,而不使用属性,这有问题吗?我应该始终通过反射中的属性获取值吗?


此扩展方法将以所需的格式构建 XElement:

public static class Extensions
{
    public static XElement ToXml<T>(this T obj)
    {
        Type type = typeof(T);

        return new XElement("Class",
                    new XElement(type.Name,
                        from pi in type.GetProperties()
                        where !pi.GetIndexParameters().Any()
                        let value = (dynamic)pi.GetValue(obj, null)
                        select pi.PropertyType.IsPrimitive || 
                               pi.PropertyType == typeof(string) ?
                                new XElement(pi.Name, value) : 
                                Extensions.ToXml(value)
                        )
                    );
    }
}

这里发生了什么:

  • 我们获取传递对象的公共属性(您可以添加 BindingFlags 来过滤属性)。
  • 接下来,我验证属性是否具有索引参数并跳过此类属性。
  • 接下来我得到的财产价值为dynamic目的。这很重要,否则属性值类型将被推断为object在递归调用期间ToXml<T> method.
  • 我检查属性类型是否为原始类型(int、byte、long、single、double 等)或字符串
  • 对于原始类型,我们编写带有属性值的元素。对于其他类型(复杂),我们递归地开始构建 XElement

Usage:

Worker worker = new Worker()
{
    Name = "Serge",
    Phone = "911",
    Address = new Address() { Street = "Elm street", ZipCode = 666 }
};

XElement xml = worker.ToXml();

Result:

<Class>
  <Worker>
    <Name>Serge</Name>
    <Phone>911</Phone>
    <Class>
      <Address>
        <Street>Elm street</Street>
        <ZipCode>666</ZipCode>
      </Address>
    </Class>
  </Worker>
</Class>

BUT 当两个对象互相引用时,你应该小心(这种情况下会发生无限递归)

在这种情况下,您可以使用字典或哈希集之类的东西来存储 xml 中已存在的所有对象:

Type type = obj.GetType();
if (set.Contains(obj))
    return new XElement("Class", new XAttribute("name", type.Name));
set.Add(obj);
return new XElement("Class", ...);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过递归使用 XElement 动态构建 Xml 的相关文章

随机推荐

  • 如何创建一个从 goroutine 接收多个返回值的通道

    我在 Go 中有一个返回两个值的函数 我想将其作为 goroutine 运行 但我无法弄清楚创建接收两个值的通道的语法 有人能指出我正确的方向吗 定义一个包含两个值字段的自定义类型 然后创建一个chan那种类型的 编辑 我还添加了一个使用多
  • 未捕获的类型错误:FB.login 不是函数

    我正在使用 Facebook JavaScript API 创建 Facebook 登录功能并从 API 获取用户详细信息 当我以正常方式使用相同的代码时 我从 Facebook api 获取数据 当我尝试使用 requireJS 做同样的
  • 如何获取当前日期之前的 30 天?

    我有一个开始日历输入框和一个结束日历输入框 我们希望默认开始日历输入框为当前日期之前 30 天 结束日历输入框默认为当前日期 这是我的日期变量 var today new Date dd today getDate mm today get
  • 从资源中读取json文件并在JAVA中将其转换为json字符串

    我在代码中硬编码了这个 JSON 字符串 String json n id 1 n name Headphones n price 1250 0 n tags home green n n 我想将其移至资源文件夹并从那里读取它 我怎样才能在
  • 在 Cocoa 中创建 iTunes 风格源列表时遇到问题

    我正在开发一款可以与 iTunes 风格的源列表配合良好的软件 我一直在网上寻找如何实现它 但所有的例子似乎都有点粗略 我找到了马克 奥尔德里特的执行 http www latenightsw com blog p 29并尝试在我的项目中使
  • CouchDB - 创建或更新文档时触发代码

    我有一个在 CouchDB 中存储数据的页面 该页面直接通过 JavaScript 访问数据库 因此浏览器中没有隐藏太多逻辑 创建新文档时 有一些逻辑将数据元素提取到单独的字段中 以便可以搜索它们 创建或更新文档时是否可以在服务器上执行此逻
  • 如何使用 [object addGesture...] 从 C4Workspace 调用方法?

    我希望实现的是使用以下方法调用 C4Workspace m 中的方法 shape addGesture SWIPELEFT name swipeLeft action leftSwipeMethod 我知道这会尝试在 C4Shape 类中调
  • jQuery livequery 插件相当于 jQuery 1.7+

    是否有相当于 jQuery 1 7 的 jQuery livequery 插件 我正在尝试动态绑定事件 读取 DOM 元素应基于 data 元素绑定的事件 a href class js test Test 1 a a href class
  • 尽可能避免使用 mod 运算符是否更好?

    我认为计算数字的模是一个有点昂贵的操作 至少与简单的算术测试 例如查看数字是否超过数组的长度 相比 如果确实如此 那么替换例如以下代码是否会更有效 res array i 1 len 与以下 res array i 1 len 0 i 1
  • DMARC/SPF 配置错误

    我有一个注册域名domains google com我使用 G Suite 帐户并从 SES 和 mailchimp 发送电子邮件 我的 DNS 记录看起来正确 Mailchimp 说明 https kb mailchimp com acc
  • reCAPTCHA - 按提交后出现

    我想在我的表单中使用 reCAPTCHA 用户必须填写表格 然后按 提交 之后 在 提交 按钮下 应该会出现 reCAPTCHA 我怎样才能做到这一点 如果我想要这样的东西 我可能会将 reCAPTCHA 预加载到jQuery 对话框 ht
  • 不可点击的锚标记

    我使用这个html代码 div class titleIn h2 a href link2 link2 a h2 div 并且由于某种原因link2不可点击 没有手形光标 CSS 是 titleIn direction rtl margin
  • SublimeText3中的binary_file_patterns和index_exclude_patterns有什么区别?

    在 Sublime Text 3 中binary file patterns排除在文件或模糊搜索 转到任何内容 中找到的文件index exclude patterns防止文件被索引 既然我们知道无法找到未索引的文件 并且假设无法追踪的文件
  • 更改资源文件 (resx) 命名空间和访问修饰符

    在我的网络项目中 我使用了 4 个资源文件App GlobalResources文件夹 其中之一 lang resx 是在我到达该项目之前创建的 它具有正确的命名空间 WebApplication App GlobalResources 和
  • 在这种情况下,为什么不从参数推断出通用值 N ?

    这个问题 TypeScript 要求两个数组长度相同 https stackoverflow com questions 62206320 typescript require that two arrays be the same len
  • 将 pandas 数据框中的逗号分隔单元格拆分为不同的列[重复]

    这个问题在这里已经有答案了 如何将逗号分隔的字符串拆分为新列 预期产出 Source Target Weight 0 Majed Moqed Majed Moqed 0 尝试这个 df Source df Source Target Wei
  • XPath - 属性通配符不返回具有名为 value 的属性的元素

    我正在尝试使用 XPath Java 来获取基于以特定值开头的未知属性的所有未知节点 由于某种原因 它没有返回包含名为的属性的节点value 我也测试过www freeformatter com xpath tester html http
  • 及时均匀地对位置时间序列进行重新采样

    正如地球科学中经常发生的那样 我有一系列位置 经度 纬度 时间序列的时间间隔不均匀 时间采样如下 t diff every position 3 99 1 00 3 00 4 00 3 98 3 99 我将位置与每个 t 相关联 lat 7
  • 读取 Jpeg2000 元数据

    我想找到一个具有 BSD MIT 或同等 许可证的开源库 该库能够读取 XML 或任何 元数据 jp2文件 迄今为止的研究 OpenJpeg https github com uclouvain openjpeg不读取元数据 EasyExi
  • 通过递归使用 XElement 动态构建 Xml

    我是 linq to Xml 的新手 我有一个递归方法作为参数XElement root它应该以表示给定递归深度的相关子树根的方式保存 XML 数据 void recursiveMethod XElement root 更具体地说 还可以看