Десериализация сложных схем xsd (содержащих элементы группы замещения для наследования) с помощью xsd.exe или xsd2code - PullRequest
4 голосов
/ 21 ноября 2011

У меня проблемы с десериализацией / сериализацией некоторых схем xsd, особенно с элементами группы замещения (substitutiongroup) внутри.Я хочу создать классы C # из схем xsd, затем обработать объект и затем сериализовать их в допустимый формат XML.Есть 4 xsd файла, которые я десериализирую и сериализую с помощью xsd2code или xsd.exe.Оба инструмента дают одинаковые неудовлетворительные результаты.Они игнорируют элементы группы замещения и не генерируют членов класса должным образом.Когда я запускаю xsd.exe или xsd2code, сгенерированный, например, класс c # для BPMNPlane не содержит члена BPMNShape (однако класс BPMNDiagram содержит BPMNPlane).Я пытался изменить сгенерированные классы C # (например, добавить члены / свойства), но сгенерированный вывод XML был неправильным.Я полагаю, что можно справиться с этим с помощью linq-to-xml, но это слишком много разных элементов, примерно 70, с дополнительными атрибутами свойств.Я новичок и не имею опыта работы с xsd или linq-to-xml, но думаю, что это лучший подход для работы со строго типизированными данными / объектами?

Ответы [ 2 ]

5 голосов
/ 24 ноября 2011

Во-первых, я поддержал ваш вопрос, так как он действительно поднимает редкий сценарий - ему также было трудно ответить, судя по тому, сколько людей передают его ... Что также означает, что вам придется сделать некоторыечтение:) ...

Краткий ответ: xsd.exe создает полезный код;это может быть не то, что вы ожидали, и я объясню почему, но это работает (по крайней мере, с моими тестами);если у вас нет проблем с обменом этого XML, то просто следуйте тому, как он генерируется.Если нет, то Linq будет работать наверняка.

Итак, основная проблема начинается с того, как была создана схема XML;учитывая, откуда он исходит Я был удивлен, увидев эту (кажущуюся) двусмысленность в стиле авторского дизайна, которая в конечном итоге также отвечает за то, почему xsd.exe, похоже, не дает ожидаемого результата.

Пожалуйста, начните с чтения этой статьи , с акцентом на разделы, называемые «Абстрактный атрибут» и «Атрибут SubstitutionGroup».

Обычно глава группы подстановки долженбыть абстрактным элементом.Хотя спецификация этого не требует, я подозреваю, что многие люди делают это предположение в своих инструментах (xsd.exe - один из них), поскольку в противном случае существует риск двусмысленности с @xsi: type.

В схеме BPMN глава групп замещения не является абстрактным (тот, на который я смотрел);более того, элементы, используемые в качестве заголовка группы замещения, имеют абстрактный тип - это звучит как xsi: type.Короче говоря, если вы посмотрите на сгенерированный код, xsd.exe создает совершенно правильный код, делая выбор между использованием или не использованием xsi: type;он пошел с первым.

Этот код ссылается на сгенерированный код xsd.exe для создания простого XML.

BPMNEdge edge = new BPMNEdge();
edge.id = "B2";
// more code here for waypoint
plane.DiagramElement1 = new DiagramElement[] { edge };

Свойство DiagramElement1 в основном принимает любой тип, производный от DiagramElementвведите, по существу, полностью заполнив контракт (и предоставив вам тип @xsi: для DiagramElement в сгенерированном XML).

XML ниже действителен;Я не мог понять, решит ли ваше резюме DiagramElement вашу проблему ... Я не думаю, что это может быть так просто, но я оставлю это на ваше усмотрение.

<?xml version="1.0" encoding="utf-16"?>
<BPMNPlane xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="A1" xmlns:q1="urn:tempuri-org:alpha" bpmnElement="q1:test" xmlns="http://www.omg.org/spec/BPMN/20100524/DI">
  <DiagramElement xmlns:q2="http://www.omg.org/spec/BPMN/20100524/DI" xsi:type="q2:BPMNEdge" id="B2" xmlns="http://www.omg.org/spec/DD/20100524/DI">
    <waypoint x="1" y="1" />
    <waypoint x="1" y="1" />
</DiagramElement>
</BPMNPlane> 

The (такжедопустимо) XML ниже был сгенерирован инструментом (не кодом, сгенерированным xsd.exe);он показывает совершенно правильную альтернативу XML, приведенному выше, с использованием членов группы подстановки, чего вы и хотели.Все, что вам нужно сделать, это выяснить, что еще нужно поставить вместо DiagramElement.Я использовал этот график, чтобы изобразить его:

enter image description here

<?xml version="1.0" encoding="utf-16"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<BPMNPlane xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="A1" xmlns:q1="urn:tempuri-org:alpha" bpmnElement="q1:test" xmlns="http://www.omg.org/spec/BPMN/20100524/DI">
    <BPMNEdge xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" p4:any_Attr="anySimpleType" bpmnElement="qname1" sourceElement="qname1" targetElement="qname1" messageVisibleKind="initiating" id="ID1" xmlns:p4="otherNS" xmlns="http://www.omg.org/spec/BPMN/20100524/DI">
        <di:extension/>
        <di:waypoint x="1" y="1"/>
        <di:waypoint x="-1.7976931348623157E+308" y="-1.7976931348623157E+308"/>
        <BPMNLabel p4:any_Attr="anySimpleType" labelStyle="qname1" id="ID2">
            <di:extension/>
            <dc:Bounds x="1" y="1" width="1" height="1"/>
        </BPMNLabel>
    </BPMNEdge>
</BPMNPlane>

Я думаю, что эта схема является идеальным примером, который показывает, как можно использовать ее в обоих направлениях (с или без xsi: typeстиль разработки) с использованием только одной схемы.Отличным тестом может быть проверка того, можно ли десериализовать этот последний XML-код с использованием кода, сгенерированного xsd.exe, и какие изменения необходимо внести, чтобы он работал.

0 голосов
/ 24 ноября 2011

спасибо за ваше время!Это хорошее объяснение!Я также обнаружил, что выполнение этого:

BPMNDiagram bpmnd = new BPMNDiagram();
BPMNPlane bpmnl = bpmnd.BPMNPlane;
 bpmnl.DiagramElement1.Add(new BPMNShape());

работает, это дает мне следующую структуру XML:

Но то, что я на самом деле хочу, это:

<bpmndi: BPMNDiagram name="bpmndiagramid">
<bpmndi: BPMNPlane>
    <bpmndi:BPMNShape id="11" bpmnElement="functionsname">
        <dc:Bounds x="0" y="0" width="0" height="0"/>
    </bpmndi:BPMNShape>
</bpmndi: BPMNPlane>
</bpmndi: BPMNDiagram >

Итак, я могу написать:

BPMNDiagram bpmnd = new BPMNDiagram();
BPMNPlane bpmnl = bpmnd.BPMNPlane;

, что дает мне:

< BPMNDiagram name="bpmndiagramid">
< BPMNPlane>...
</ BPMNPlane>
</ BPMNDiagram >

Но не напрямую это:

BPMNDiagram bpmnd = new BPMNDiagram();
BPMNPlane bpmnl = bpmnd.BPMNPlane;
BPMNShape myShape = bpmnl.BPMNShape;

Я подумал, что было бы быстрее, чем работать с LINQ 2 XML, создавать классы c # и работать с ними, но теперь я вижу, что мне нужно углубиться в XML-схему / элементы и т. Д.

...