使用 XML 序列化设置元素/属性值的格式
我有一个代表信用卡详细信息的课程。 为了表示有效的起始月份和到期月份和年份,我使用了 int
类型的四个属性:
public int ValidFromMonth { get; set; }
public int ValidFromYear { get; set; }
public int ExpiresEndMonth { get; set; }
public int ExpiresEndYear { get; set; }
我正在对此类进行 XML 序列化以供第三方使用。 如果值小于 10,该第三方要求我的月份和年份值以前导零为前缀。.NET
<validFromMonth>02</validFromMonth>
<validFromYear>09</validFromYear>
<expiresEndMonth>10</expiresEndMonth>
<expiresEndYear>14</expiresEndYear>
是否支持任何将强制执行此规则的属性(或者我是否可以创建自定义属性),可能使用格式字符串(例如 {0:00}
)?
注意:我知道我可以添加自己的 string
属性来在内部进行格式化,并将 [XmlIgnore]
属性添加到我的 int
属性中,但这感觉像是一个二流的解决方案。
编辑: 经过一番考虑后,我想知道这是否实际上不可行。 序列化不会有问题,但为了反序列化工作,您需要取消序列化字符串的格式。 在上面的小例子中,这很容易,但我不确定它是否可以在更一般的情况下工作。
编辑2: 定义两位数要求的 XML 架构如下。
简单类型定义:
<xs:simpleType name="CreditCardMonthType">
<xs:annotation>
<xs:documentation>Two digit month</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:minLength value="2" />
<xs:maxLength value="2" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="CreditCardYearType">
<xs:annotation>
<xs:documentation>Two digit year</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:minLength value="2" />
<xs:maxLength value="2" />
</xs:restriction>
</xs:simpleType>
使用这些类型的信用卡定义:
<xs:attribute name="ExpiryMonth" type="CreditCardMonthType" use="required">
<xs:annotation>
<xs:documentation>Credit/debt card's expiry month.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExpiryYear" type="CreditCardYearType" use="required">
<xs:annotation>
<xs:documentation>Credit/debt card's expiry year.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="StartMonth" type="CreditCardMonthType" use="optional">
<xs:annotation>
<xs:documentation>Switch card's start month.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="StartYear" type="CreditCardYearType" use="optional">
<xs:annotation>
<xs:documentation>Switch card's start year.</xs:documentation>
</xs:annotation>
</xs:attribute>
I have a class that represents credit card details. To represent valid from and expiration months and years I am using four properties of type int
:
public int ValidFromMonth { get; set; }
public int ValidFromYear { get; set; }
public int ExpiresEndMonth { get; set; }
public int ExpiresEndYear { get; set; }
I am XML Serializing this class for consumption by a third party. That third party requires my month and year values to be prefixed with a leading zero if the value is less than 10
<validFromMonth>02</validFromMonth>
<validFromYear>09</validFromYear>
<expiresEndMonth>10</expiresEndMonth>
<expiresEndYear>14</expiresEndYear>
Does .NET support any attribution (or is it possible for me to create a custom attribute) that will enforce this rule, possibly using a format string (e.g. {0:00}
)?
Note: I know that I could add my own string
properties that do the formatting internally, and add an [XmlIgnore]
attribute to my int
properties, but this feels like a second-rate solution.
Edit:
After some consideration I am wondering if this is actually just not feasible. Serialization would be no problem, but in order for deserialization to work you would need to un-format the serialized string. In the trivial example above this would be easy, but I am not sure that it could be made to work in the more general case.
Edit2:
The XML Schema that defines the two-digit requirement is below.
Simple type definitions:
<xs:simpleType name="CreditCardMonthType">
<xs:annotation>
<xs:documentation>Two digit month</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:minLength value="2" />
<xs:maxLength value="2" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="CreditCardYearType">
<xs:annotation>
<xs:documentation>Two digit year</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:minLength value="2" />
<xs:maxLength value="2" />
</xs:restriction>
</xs:simpleType>
Credit card definition that uses these types:
<xs:attribute name="ExpiryMonth" type="CreditCardMonthType" use="required">
<xs:annotation>
<xs:documentation>Credit/debt card's expiry month.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExpiryYear" type="CreditCardYearType" use="required">
<xs:annotation>
<xs:documentation>Credit/debt card's expiry year.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="StartMonth" type="CreditCardMonthType" use="optional">
<xs:annotation>
<xs:documentation>Switch card's start month.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="StartYear" type="CreditCardYearType" use="optional">
<xs:annotation>
<xs:documentation>Switch card's start year.</xs:documentation>
</xs:annotation>
</xs:attribute>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好的,忽略我之前的代码示例(不过,我将保留它,因为它可能对其他人有帮助)。 我刚刚记得您可以使用 XmlEnumAttribute:
然后将您的用法更改为枚举:
这实际上是一种非常好的方法,因为您现在有了该月的枚举(这确实是您从一开始就应该做的事情)。
OK, ignore my previous code sample (I'll leave it up since it might help somebody else, though). I just remembered you can do this using XmlEnumAttribute:
and then change your usage to the enum:
This is actually a very nice way since you now have an enum for the month (which is really what you should've done from the beginning).
这是很多代码,但它可以满足您的要求。 要点是,您可以创建一个新类(本例中为
LeadingZero
)并实现IXmlSerialized
来控制从 XML 流中读取/写入的方式。 希望这有帮助:这是我得到的输出:
This is a lot of code, but it does what you want. The gist is that you can create a new class (
LeadingZero
in this example) and implementIXmlSerializable
to control how you read/write from the XML stream. Hope this helps:This is the output that I got:
此类需求通常来自不懂 XML 的公司。 我不会假设这里是这种情况,而是会问:他们是否为您提供了描述前导零日格式的 XML 模式? 如果是这样,您能发布其中定义这一天的部分吗?
基于编辑进行编辑
感谢您发布架构。 这证实了我担心的另一件事。 你的整数不是整数。 请注意
。 这些是字符串,而不是整数。This sort of requirement often comes from companies that don't understand XML. Rather than assume this is the case here, I'll ask: did they supply you with XML schema that describes the leading-zero day format? If so, could you post the part of it that defines the day?
EDIT based on edit
Thanks for posting the schema. It confirmed the other thing I was concerned about. Your integers are not integers. Note the
<restriction base="xs:string"/>
. These are strings, not integers.使用 XmlEnum 的缺点是它不能为空,
我会推荐
这将允许您使属性可以为空
Disadvatage using XmlEnum is that it can't be nullable
i will Recommand
This will allow you to make attribute nullable