Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何根据生成的.Net类或原始XSD中的元素/属性名从xml文件中提取字符串形式的值?_C#_.net_Xml_Validation_Serialization - Fatal编程技术网

C# 如何根据生成的.Net类或原始XSD中的元素/属性名从xml文件中提取字符串形式的值?

C# 如何根据生成的.Net类或原始XSD中的元素/属性名从xml文件中提取字符串形式的值?,c#,.net,xml,validation,serialization,C#,.net,Xml,Validation,Serialization,我有一个大型复杂的XSD集 我使用xsd.exe从这些xsd生成了C#类。当然,尽管生成的类中的大多数属性都是strings,但许多属性都是decimals、DateTimes、enums或bools,它们应该是这样的 现在,我有一些以正确的XML格式构造的未验证数据,但可能无法通过XSD验证,更不用说放入相关.Net对象的实例中了。例如,在这个阶段,据我们所知,应该是DateTime的元素的值可以是“ABC”-甚至不能解析为DateTime-更不用说其他关于maxLength或regex模式限

我有一个大型复杂的XSD集

我使用xsd.exe从这些xsd生成了C#类。当然,尽管生成的类中的大多数属性都是
string
s,但许多属性都是
decimal
s、
DateTime
s、
enum
s或
bool
s,它们应该是这样的

现在,我有一些以正确的XML格式构造的未验证数据,但可能无法通过XSD验证,更不用说放入相关.Net对象的实例中了。例如,在这个阶段,据我们所知,应该是DateTime的元素的值可以是“ABC”-甚至不能解析为DateTime-更不用说其他关于maxLength或regex模式限制的字符串元素了。这些数据已经准备好传递给规则引擎,我们已经必须使所有内容都有效,包括根据其他数据项适当地进行缺省设置,等等

我知道如何使用
System.Xml
中的各种类型按名称读取给定元素的字符串值。很明显,我可以手工编写代码,以按名称列出当前存在的所有元素——但如果XSD发生更改,则需要重新编写代码。我希望能够直接读取XSD或在生成的类上使用反射(必要时包括
[System.Xml.Serialization.XmlTypeAttribute(TypeName=…])
等属性)要准确地找到如何递归地查询XML,直到任何给定元素的原始、未经验证的字符串版本传递到规则集,然后在规则使其生效后,将其放回强类型对象或放回XML副本,以便序列化到对象中

(我突然想到,另一种方法是以某种方式自动生成对象的“”版本(其中没有日期时间等;只有字符串),并将xml序列化到该版本中。我甚至疯狂地考虑使用xsd.exe生成的.cs文件,搜索/替换所有非字符串的枚举和基类型。)s到字符串,但必须有更好的方法。)


换句话说,是否有一种现有的通用方法可以从一些XML中提取XElement或属性值,这些XML如果被序列化,将与.Net类中的给定项相对应,而不实际序列化它?

对不起,请自行回答,对不起,我的回答中缺少实际代码,但我还没有e我的雇主允许我分享这方面的实际代码。在这方面的工作,我会在这里更新时,有运动

我能够实现一个我称之为
宽容的XML阅读器
。与大多数XML反序列化不同,它首先使用反射来查看所需.Net类型的结构,然后尝试查找相关的元素并解释它们。任何额外的元素都会被忽略(因为它们从未被查找),未找到的任何元素都将被默认,找到的任何元素都将被进一步解释

以C#表示的主要方法签名如下:

public static T TolerantDeserializeIntoType<T>(
            XDocument doc,
            out List<string> messagesList,
            out bool isFromSuppliedData,
            XmlSchemaSet schemas = null,
            bool tolerant = true)
public static T TolerantDeserializeIntoType(
XDocument doc,
输出列表消息列表,
我是从Supplieddata来的,
XmlSchemaSet schemase=null,
bool容差=真)
对它的典型调用可能如下所示:

List<string> messagesList;
bool defaultOnly;
SomeType result = TolerantDeserializeIntoType<SomeType>(someXDocument, out messagesList, out defaultOnly);
列表消息列表;
仅限布尔值;
SomeType结果=TolerantDeserializeIntoType(someXDocument,out messagesList,out defaultOnly);
(您可以使用var;在本例中,为了清楚起见,我只是显式地将类型放在那里)

这将获取anyXDocument(因此原始文档的唯一标准是格式良好),并从中生成指定类型的实例(本例中为SomeType)

请注意,即使XML中没有任何内容被识别,它也不会失败。新实例的所有属性/公共字段都将为null或默认值,MessageList将列出所有已完成的默认值,boolean out参数将为FALSE

完成所有工作的递归方法具有类似的签名,只是它采用XElement而不是XDocument,并且不采用schemaSet。(当前的实现也有一个显式bool来指示默认为false的递归调用。这是一种稍微脏一点的方式,允许它在抛出错误之前收集所有失败消息,如果容错为false;在未来的版本中,我将重构它,以仅公开一个没有该错误的版本,如果我甚至想XElement版本(完全公开):

公共静态T公差反序列化XelementInType(
参考XElement元素,
参考列表消息列表,
out bool是来自SuppliedValue,
布尔宽容=真,
bool recursiveCall=false)
它的工作原理、细节

从主调用开始,该调用包含XDocument和可选SchemaSet:

如果提供了将要编译的模式集(实际上,它还查找xsi:noNamespaceSchemaLocation),那么初始XDocument和schemaSet调用将运行标准XDocument.Validate()在提供的XDocument中,但这只收集任何已发出的验证错误回调。它不会引发异常,并且只有两个原因:

  • 它将为MessageList提供一些有用的消息,以及
  • 它会将所有元素的SchemaInfo填充到 可能在XElement版本中稍后使用

    (但是,请注意 模式是完全可选的。它实际上只用于解析 一些模棱两可的情况下,它可以从C不清楚# 对象(如果给定的元素是必需的或不是。)

  • 从那里,在根节点上调用递归XElement版本,然后
    public static T TolerantDeserializeXElementIntoType<T>(
                ref XElement element,
                ref List<string> messagesList,
                out bool isFromSuppliedValue,
                bool tolerant = true,
                bool recursiveCall = false)