jjzjj

c# - IXmlSerializable 验证模式

coder 2024-07-04 原文

我正在实现 IXmlSerializable对于我的类的自定义(反)序列化逻辑,但希望根据 XSD 模式检查 XML 的读写。我添加了 XmlSchemaProviderAttribute :

[XmlSchemaProvider("ConfigSchema")]
[XmlRoot("Config")]
public class Config
{
    // properties, fields and methods incl. interface methods

    public static XmlQualifiedName ConfigSchema(XmlSchemaSet xs)
    {
        const string xsdPath = "./Config.xsd";

        var serializer = new XmlSerializer(typeof(XmlSchema));
        var schema = (XmlSchema)serializer.Deserialize(new XmlTextReader(xsdPath), null);

        xs.XmlResolver = new XmlUrlResolver();
        xs.Add(schema);

        return new XmlQualifiedName("Config", "namespace");
    }
}

模式加载正常,(反)序列化按预期工作,但没有验证。

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="ConfigSchema" 
    targetNamespace="namespace"
    elementFormDefault="qualified"
    xmlns="namespace"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:complexType name="Config">
        <xs:all>
            <xs:element name="Config">
                <xs:complexType>
                    <xs:all>
                        <xs:element name="name" type="xs:string" />
                        <xs:element name="timeout" type="xs:time" />
                        <xs:element name="points" minOccurs="1">
                            <xs:complexType>
                                <xs:sequence>
                                    <xs:element name="point" minOccurs="1" maxOccurs="unbounded">
                                        <xs:complexType>
                                            <xs:all>
                                                <xs:element name="a" type="xs:int" />
                                                <xs:element name="b" type="xs:int" />
                                                <xs:element name="c" type="xs:int" />
                                            </xs:all>
                                        </xs:complexType>
                                    </xs:element>
                                </xs:sequence>
                            </xs:complexType>
                        </xs:element>
                    </xs:all>
                </xs:complexType>
            </xs:element>
        </xs:all>
    </xs:complexType>
</xs:schema>

如果我根据上述架构反序列化以下内容,则不会引发异常(缺少 <timeout> 但在架构中的 <xs:all> 下指定):

<?xml version="1.0" encoding="utf-8" ?>
    <Config
        xmlns:xsi="http://w3.org/2001/XMLScehma-instance"
        xsi:schemaLocation="namespace Config.xsd">
        <name>some name</name>
        ...

编辑:这是我运行它的方式

string path = "./serviceconfig.xml";
var serializer = new XmlSerializer(typeof(Config));
var cfg = (Config)serializer.Deserialize(new XmlTextReader(path), null);

根据架构验证传入/传出 XML 的“正确”/“最佳”方法是什么?

编辑#2:更多信息

这是完整的 XML

<?xml version="1.0" encoding="utf-8" ?>
    <Config
        xmlns:xsi="http://w3.org/2001/XMLScehma-instance"
        xsi:schemaLocation="namespace Config.xsd">
        <name>some name</name>
        <timeout>10</timeout>
        <points>
            <point>
                <a>5</a>
                <b>7</b>
                <c>11</c>
            </point>
            <point>
                <a>8</a>
                <b>7</b>
                <c>3</c>
            </point>
        </points>
    </Config>

我已经尝试查看 ReadXml(XmlReader reader) 中的 XmlReaderSettings|以下内容没有帮助

var settings = new XmlReaderSettings
{
    ValidationType = ValidationType.Schema,
    Schemas = _schemaSet
};

settings.ValidationEventHandler += (sender, args) => Console.WriteLine(args.Message);
reader = XmlReader.Create(reader, settings);

_schema从静态 ConfigSchema() 设置以上。

最佳答案

XML 未通过验证,因为您的模式指定了 targetNamespace = "namespace" 但您的 XML 实例未使用 xmlns 引用此命名空间。

所以验证器不知道如何验证您的 XML,因为它没有意识到您的 XML 使用您的模式中定义的类型。

如果您发布完整的架构和 xml 实例,我将能够制作一个工作示例。

更新

感谢您发布您的架构。你在哪里得到它?我问的原因是它没有定义任何根节点,只是一个名为 Config 的类型。

如果删除外部复杂类型元素:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="ConfigSchema"
    targetNamespace="namespace"
    elementFormDefault="qualified"
    xmlns="namespace"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Config">
    <xs:complexType>
      <xs:all>
        <xs:element name="name" type="xs:string" />
        <xs:element name="timeout" type="xs:time" />
        <xs:element name="points" minOccurs="1">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="point" minOccurs="1" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:all>
                    <xs:element name="a" type="xs:int" />
                    <xs:element name="b" type="xs:int" />
                    <xs:element name="c" type="xs:int" />
                  </xs:all>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:all>
    </xs:complexType>
  </xs:element>
</xs:schema>

我能够验证以下实例:

<?xml version="1.0" encoding="utf-8" ?>
<Config xmlns="namespace">
  <name>some name</name>
  <timeout>13:20:00.000-05:00</timeout>
  <points>
    <point>
      <a>5</a>
      <b>7</b>
      <c>11</c>
    </point>
    <point>
      <a>8</a>
      <b>7</b>
      <c>3</c>
    </point>
  </points>
</Config>

请注意,根据架构,“10”不是超时列的有效值。当我尝试时出现此错误:

The 'namespace:timeout' element is invalid - The value '10' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:time' - The string '10' is not a valid XsdDateTime value.

关于c# - IXmlSerializable 验证模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21284592/

有关c# - IXmlSerializable 验证模式的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  6. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  7. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  8. ruby-on-rails - 如何将验证与模型分开 - 2

    我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:

  9. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  10. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

随机推荐