简体   繁体   中英

How to get a flat list of possible XML Elements in order from a XmlSchemaObject in .NET

I have a XML Schema from a XmlSchemaSetProvider and need a list of all possible XML Elements (names) that may be in the given type in the correct order.

The schema uses XML Schema extensions, complex types, sequences...

Is there some good way to accomplish this?

Cause: I have a custom XML serializer that depended on property order returned when reflecting the .NET type but that (documented as undefined) order behavior changed with MSBuild 14. Now i have to correct the order without putting around 1000 XmlElement.Order on all class properties. So the idea is to detect/correct the order from XSD information and use it to fix the XML.

In the general case, what you are asking for is not possible. If the type can contain N different elements, then it is possible to design a schema in which some subset of the elements can appear in a different sequence depending on the context. So there is no such thing as a single defined sequence for all of the elements in the schema. The particular schemas that you have in mind may not suffer from this problem (although you should assume the worst until you can prove that they do not). If you believe that a solution is possible for this restricted set of schemas then you will need to design a custom solution, and I would advise you to design it pretty conservatively. In particular, you should include assertions that check for scenarios that break your only-one-possible-sequence rule.

Having said all of that, I would be interested to understand the business requirement behind your request. It might be possible to solve this by some other ( easier ) means.

In the end I chose a different approach based on class layout instead of the XML Schema. I added a "[PropertyLineNumber]" on all properties with one search & replace and use it via reflection to get a reliable order. The order goes by "inheritance chain then line number". Here the attribute (using C# 6) I used to make line number information available via reflection for our serializer.

[AttributeUsage(AttributeTargets.Property)]
public sealed class PropertyLineNumberAttribute : Attribute
{
    public int LineNumber { get; }

    public PropertyLineNumberAttribute([CallerLineNumber] int lineNumber = 0)
    {
        LineNumber = lineNumber;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM