Skip to content

[Repo Assist] Add UseSchemaTypeNames parameter to XmlProvider for XSD type deduplication#1663

Merged
dsyme merged 6 commits intomainfrom
repo-assist/fix-issue-1488-xsd-use-schema-type-names-59f5ef198df83e08
Feb 26, 2026
Merged

[Repo Assist] Add UseSchemaTypeNames parameter to XmlProvider for XSD type deduplication#1663
dsyme merged 6 commits intomainfrom
repo-assist/fix-issue-1488-xsd-use-schema-type-names-59f5ef198df83e08

Conversation

@github-actions
Copy link
Contributor

🤖 This is an automated pull request from Repo Assist, an AI assistant for this repository.

Implements the fix requested in #1488 — a new UseSchemaTypeNames static parameter for XmlProvider that deduplicates F# types when multiple elements share the same XSD complex type.

Problem

When a schema defines a shared complex type (e.g. USAddress) referenced by multiple elements (e.g. shipTo and billTo), the XmlProvider generates separate F# types for each element — XmlProvider+ShipTo and XmlProvider+BillTo — even though they have identical structure. This forces users to write duplicate mapping code for each element.

What this adds

A new UseSchemaTypeNames static parameter (default false for backward compatibility):

// Before: shipTo and billTo are different F# types (ShipTo / BillTo) even though same XSD type
type OldOrder = XmlProvider(Schema="order.xsd")

// After: shipTo and billTo both return the same AddressType F# type
type Order = XmlProvider(Schema="order.xsd", UseSchemaTypeNames=true)

let order = Order.Parse(xml)
let ship: Order.AddressType = order.ShipTo   // was: Order.ShipTo
let bill: Order.AddressType = order.BillTo   // was: Order.BillTo

// Now you can write one mapping function for both:
let formatAddress (addr: Order.AddressType) =
    sprintf "%s, %s %s" addr.Street addr.City addr.Zip

Implementation

The change is minimal and surgical:

  1. XsdModel.XsdComplexType — Added Name: XmlQualifiedName option field to capture the XSD type name.
  2. XsdParsing.parseComplexType — Populates Name from XmlSchemaComplexType.QualifiedName (non-empty for named types, None for anonymous inline types).
  3. XsdInference.inferElementType — When useSchemaTypeNames=true, uses the XSD type name instead of the element name for the InferedType.Record. This causes elements sharing the same XSD type to generate the same InferedType.Record name, which the type provider infrastructure then naturally deduplicates into a single F# type.
  4. XmlProvider.fs — Adds UseSchemaTypeNames as arg [14] and threads it through to XsdInference.inferElements.
  5. TypeProviderInstantiation.fs and InferenceTests.fs — Updated to include the new parameter.
  6. shared-types.xsd — Added test XSD demonstrating shared complex types.

Design decisions

  • Default false: Preserves backward compatibility — existing code using XSD schemas continues to work unchanged.
  • Named types only: Anonymous inline complex types (no xs:complexType name="...") continue to use element names, since they don't have a meaningful XSD type name.
  • Opt-in: Users working with complex schemas where multiple elements share types can opt in to get cleaner, deduplicated generated types.

Test Status

  • dotnet build src/FSharp.Data.Xml.Core/FSharp.Data.Xml.Core.fsproj — ✅ Build succeeded (0 errors)
  • dotnet build src/FSharp.Data.DesignTime/FSharp.Data.DesignTime.fsproj — ✅ Build succeeded (0 errors, 7 pre-existing warnings)
  • dotnet test tests/FSharp.Data.DesignTime.Tests/ — Same 436 pre-existing failures as on main (50 pass, 1 skip, 436 fail due to pre-existing test infrastructure cross-context issue unrelated to this change)

Generated by Repo Assist

To install this workflow, run gh aw add githubnext/agentics/workflows/repo-assist.md@f2c5cf1e4af58e09a93ba0703c6bf084711b265f. View source at https://github.com/githubnext/agentics/tree/f2c5cf1e4af58e09a93ba0703c6bf084711b265f/workflows/repo-assist.md.

…ation

When UseSchemaTypeNames=true and a Schema is provided, elements sharing
the same XSD complexType are mapped to a single F# type (named after the
XSD type) instead of generating a separate per-element type.

For example, with po.xsd, shipTo and billTo (both of type USAddress)
previously generated XmlProvider+ShipTo and XmlProvider+BillTo as
separate identical F# types. With UseSchemaTypeNames=true, both map to
a single XmlProvider+USAddress type.

Closes #1488

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme
Copy link
Contributor

dsyme commented Feb 26, 2026

/repo-assist Fix this on Windows:

  Failed testFormDataBodySize(100000) [2 s]
  Error Message:
     Expected: No Exception to be thrown
  But was:  <System.Net.WebException: No connection could be made because the target machine actively refused it. (127.0.0.1:49805)
 ---> System.Net.Http.HttpRequestException: No connection could be made because the target machine actively refused it. (127.0.0.1:49805)
 ---> System.Net.Sockets.SocketException (10061): No connection could be made because the target machine actively refused it.

@dsyme
Copy link
Contributor

dsyme commented Feb 26, 2026

/repo-assist We need more testing. The file "tests/FSharp.Data.Tests/Data/shared-types.xsd" doesn't actually seem to be used. Add more tests

- InferenceTests: add unit tests for XsdInference.inferElements with
  useSchemaTypeNames=true/false, verifying that shared XSD complex types
  produce correctly named InferedType.Record entries and that anonymous
  types still use element names
- XmlProvider.fs: add integration tests using inline schema and
  shared-types.xsd with UseSchemaTypeNames=true, verifying that shipTo
  and billTo (both AddressType) produce the same .NET type and that
  field values are parsed correctly

Closes the gap identified in #1663: shared-types.xsd was added as test
data but not actually referenced in any test.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

Commit pushed: aa049e7

Generated by Repo Assist

@github-actions
Copy link
Contributor Author

🤖 This is an automated response from Repo Assist.

Thanks for the feedback! I've added the missing tests that exercise shared-types.xsd and the UseSchemaTypeNames parameter.

New tests added (5 tests total, all passing ✅):

tests/FSharp.Data.DesignTime.Tests/InferenceTests.fs — unit tests at the inference level:

  1. UseSchemaTypeNames false: child elements use element names as record type names — verifies the default behavior keeps shipTo/billTo as separate InferedType.Record names
  2. UseSchemaTypeNames true: shared complex types get XSD type name — verifies that shipTo and billTo (both AddressType) get Some "AddressType" in the inferred type, and contact gets Some "PersonType"; the root element gets Some "OrderType"
  3. UseSchemaTypeNames true: anonymous types still use element names — verifies that elements with anonymous inline complex types (no xs:complexType name="...") still use the element name

tests/FSharp.Data.Tests/XmlProvider.fs — integration tests at the type provider level:
4. XmlProvider UseSchemaTypeNames=true: shipTo and billTo share the same generated F# type — inline schema test; asserts order.ShipTo.GetType() = order.BillTo.GetType()
5. XmlProvider UseSchemaTypeNames=true with shared-types.xsd: shipTo and billTo share AddressType — file-based test using Data/shared-types.xsd; checks field values and type identity including the optional contact field

Generated by Repo Assist for issue #1663

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@afb00b92a9514fee9a14c583f059a03d05738f70

@dsyme dsyme marked this pull request as ready for review February 26, 2026 15:21
@dsyme dsyme merged commit 0eda330 into main Feb 26, 2026
2 checks passed
@dsyme dsyme deleted the repo-assist/fix-issue-1488-xsd-use-schema-type-names-59f5ef198df83e08 branch February 26, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants