xs:integer as System.Int64

 
Digging in, XML Schema Part 2 says xs:integer is derived from xs:decimal (sans fraction), and "minimally conforming" processors must support a minimum of 18 decimal digits. Since System.Int64 provides a little over 18 decimal digits, it would be "minimally compliant" to import xs:integer etc as System.Int64.
 
For just such eventualities, Whidbey defines SchemaImporterExtension; it sits in the middle of the XML Schema import process and maps types on the fly. Here is a sample that does the above mapping.
 
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
 
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Xml.Serialization.Advanced;
using System.CodeDom;
using System.CodeDom.Compiler;
 
namespace Microsoft.Samples.Xml.Serialization.SchemaImporterExtension
{
  publicclass ImportInteger
    : System.Xml.Serialization.Advanced.SchemaImporterExtension
  {
    publicoverridestring ImportSchemaType(
      string name,
      string ns,
      XmlSchemaObject context,
      XmlSchemas schemas,
      XmlSchemaImporter importer,
      CodeCompileUnit compileUnit,
      CodeNamespace mainNamespace,
      CodeGenerationOptions options,
      CodeDomProvider codeProvider
    )
    {
      if (XmlSchema.Namespace == ns)
      {
        switch (name)
        {
          case"integer":
            returntypeof(System.Int64).FullName;
          case"negativeInteger":
            returntypeof(System.Int64).FullName;
          case"nonNegativeInteger":
            returntypeof(System.UInt64).FullName;
          case"nonPositiveInteger":
            returntypeof(System.Int64).FullName;
          case"positiveInteger":
            returntypeof(System.UInt64).FullName;
          default:
            returnnull;
        }
      }
      else
      {
        returnnull;
      }
    }
  }
}
 
To use this, compile the above assembly, generate a strong name, add the assembly to the GAC, and reference the assembly in machine.config. Here is what machine.config looks like on my machine:
 
<configuration>
  <configSections>
    ...
  </configSections>
  ...
  <system.xml.serialization
>
    <schemaImporterExtensions>
      <addname="MyImporter"type="Microsoft.Samples.Xml.Serialization.SchemaImporterExtension.ImportInteger, ImportInteger, Version=0.0.0.0, Culture=neutral, PublicKeyToken=3c3789dee90b3265" />
    </schemaImporterExtensions>
  </system.xml.serialization>
</configuration>
 
Because SchemaImporterExtension is integrated pretty deeply into the ASMX infrastructure, the good news is that the above just works with Add Web Reference, wsdl.exe, and xsd.exe!
 
P.S. I added an optimization to map xs:positiveInteger and xs:nonNegativeInteger to System.UInt64. If CLS compliance is important in what you're doing, you probably want to map these to System.Int64 too.

Posted Jun 21 2005, 11:10 PM by jeffrey-schlimmer

Comments

Dilip wrote re: xs:integer as System.Int64
on 06-22-2005 9:12 AM
You should try Dingo (http://sourceforge.net/projects/dingo)
Supposed to do a better job than XSD.exe in mapping XSD types to C# data types.
Marvin Smit wrote re: xs:integer as System.Int64
on 07-25-2005 2:49 AM
Hi,

although my initial thought was the same (xsd:integer => string ???).

but since the specs says:
[quote]
The ·value space· of integer is the infinite set {...,-2,-1,0,1,2,...}
[/quote]

Isn't there a problem when using fixed (xx bit) sized values? (We might not run into them easy, but eventually will)

Marvin Smit.

Ps: I'm not defending the XSD tool, there's much to be improved there, but.....
Jeffrey Schlimmer wrote re: xs:integer as System.Int64
on 07-25-2005 6:43 AM
I agree xs:*integer should really map big integers -- when .NET has them -- but xs:long is compliant if not completely living up to the intention of the spec.

In the meantime, when people use xs:*integer, we're asking them if they really meant the infinite set and often find that their intention was a large, but finite, integer.
Tom Ekberg wrote re: xs:integer as System.Int64
on 09-05-2005 5:52 AM
I changed the XSD file to use the xs:long type instead of the xs:integer type. The xsd.exe program generated those variables as longs instead of Strings. This works well for those cases where one can specify the type.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?