Я пытаюсь обеспечить ограничение уникальности для комбинации атрибутов двух элементов, используя XSD. Ограничение корректно работает в Notepad++, но не в моем приложении C#.
Я добавил в свой XSD следующий уникальный оператор:
<xs:unique name = "uniqueEMNameParentID">
<xs:selector xpath = ".//EM"/>
<xs:field xpath = "@Name"/>
<xs:field xpath = ".//Station/@ID"/>
</xs:unique>
И это пример моего XML:
<?xml version = "1.0" encoding = "utf-8"?>
<Project>
<PLC Name = "PLC">
<Type>
<TypeDef ID = "1" Name = "G05" Description = "" />
</Type>
<SA ID = "01">
<Station ID = "100">
<EM ID = "01" Name = "IR01" IsRobot = "TRUE">
</EM>
</Station>
</SA>
<SA ID = "02">
<Station ID = "100">
<EM ID = "02" Name = "IR01" IsRobot = "TRUE">
</EM>
<EM ID = "03" Name = "IR03" IsRobot = "TRUE">
</EM>
</Station>
</SA>
</PLC>
</Project>
При использовании Notepad++ XSD выдает правильную ошибку: «IR01 — это дубликат ключа для ограничения уникальной идентификации «uniqueEMNameParentID». Однако при проверке того же XML на соответствие XSD на C# с использованием приведенного ниже кода ошибка не выдается:
private void ValidateXML()
{
XmlSchemaSet schema = new XmlSchemaSet();
schema.Add("", @"Z:\VMshare\Maarten\WindowsFormsApplication3\WindowsFormsApplication3\XML\XSDScheme3.xsd");
projectXML.Schemas.Add(schema);
projectXML.Validate((object sender, System.Xml.Schema.ValidationEventArgs args) =>
{
MessageBox.Show(args.Message);
});
}
Мой XML-документ не содержит никаких пространств имен, мой XSD не содержит целевого пространства имен, а для атрибута и elementformdefault установлено значение неквалифицированное. Кто-нибудь знает, что это может быть?
Обратите внимание, что мой XML содержит два элемента Station с идентификатором атрибута = 100. Оба этих элемента имеют дочерний элемент EM с именем атрибута = IR01. Это не должно быть возможным.
Полный XSD:
<xs:schema attributeFormDefault = "unqualified" elementFormDefault = "unqualified" xmlns:xs = "http://www.w3.org/2001/XMLSchema">
<xs:element name = "Project">
<xs:complexType>
<xs:sequence>
<xs:element name = "PLC">
<xs:complexType>
<xs:sequence>
<xs:element name = "Type">
<xs:complexType>
<xs:sequence>
<xs:element name = "TypeDef">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:byte" name = "ID"/>
<xs:attribute type = "xs:string" name = "Name"/>
<xs:attribute type = "xs:string" name = "Description"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "SA" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:sequence>
<xs:element name = "Station" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:sequence>
<xs:element name = "EM" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:sequence>
<xs:element name = "Robot">
<xs:complexType>
<xs:sequence>
<xs:element name = "Jobs">
<xs:complexType>
<xs:sequence>
<xs:element name = "Job" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:byte" name = "ID" use = "required"/>
<xs:attribute type = "xs:string" name = "Description" use = "required"/>
<xs:attribute type = "xs:string" name = "Type" use = "optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "Areas">
<xs:complexType>
<xs:sequence>
<xs:element name = "Area" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:byte" name = "ID" use = "required"/>
<xs:attribute type = "xs:string" name = "Description" use = "required"/>
<xs:attribute type = "xs:string" name = "TargetEM_No" use = "optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "Userbits">
<xs:complexType mixed = "true">
<xs:sequence>
<xs:element name = "Userbit" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType mixed = "true">
<xs:sequence>
<xs:element name = "Reference" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:byte" name = "Area" use = "optional"/>
<xs:attribute type = "xs:byte" name = "Job" use = "optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type = "xs:byte" name = "ID" use = "required"/>
<xs:attribute type = "xs:string" name = "Description" use = "required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "FZones">
<xs:complexType mixed = "true">
<xs:sequence>
<xs:element name = "FZone" minOccurs = "0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:byte" name = "ID" use = "optional"/>
<xs:attribute type = "xs:string" name = "Function" use = "optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "Programs">
<xs:complexType>
<xs:sequence>
<xs:element name = "Program" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:byte" name = "ID" use = "required"/>
<xs:attribute type = "xs:string" name = "JobSequence" use = "required"/>
<xs:attribute type = "xs:byte" name = "Home" use = "required"/>
<xs:attribute type = "xs:string" name = "Sheet" use = "required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "Tools">
<xs:complexType>
<xs:sequence>
<xs:element name = "Tool" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:byte" name = "ID" use = "required"/>
<xs:attribute type = "xs:string" name = "Type" use = "required"/>
<xs:attribute type = "xs:string" name = "Name" use = "required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "UserNumbers">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:string" name = "NumberRequired" use = "required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type = "xs:string" name = "Name" use = "optional"/>
<xs:attribute type = "xs:string" name = "Manufacturer" use = "optional"/>
<xs:attribute type = "xs:byte" name = "RobotIndex" use = "optional"/>
</xs:complexType>
</xs:element>
<xs:element name = "TypePlaceholder" minOccurs = "0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:string" name = "Name"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type = "xs:byte" name = "ID" use = "required"/>
<xs:attribute type = "xs:string" name = "Name" use = "required"/>
<xs:attribute type = "xs:string" name = "IsRobot" use = "required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type = "xs:short" name = "ID" use = "optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type = "xs:byte" name = "ID" use = "optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type = "xs:string" name = "Name"/>
</xs:complexType>
</xs:element>
<xs:element name = "ImportDocuments">
<xs:complexType>
<xs:sequence>
<xs:element name = "HandshakeDocument" maxOccurs = "unbounded" minOccurs = "0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base = "xs:string">
<xs:attribute type = "xs:string" name = "Name" use = "required"/>
<xs:attribute type = "xs:string" name = "ImportDate" use = "required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:unique name = "uniqueEMNameParentID">
<xs:selector xpath = ".//EM"/>
<xs:field xpath = "@Name"/>
<xs:field xpath = ".//Station/@ID"/>
</xs:unique>
</xs:element>
</xs:schema>
Полный XML
<?xml version = "1.0" encoding = "utf-8"?>
<Project>
<PLC Name = "PLC">
<Type>
<TypeDef ID = "1" Name = "G05" Description = "" />
</Type>
<SA ID = "01">
<Station ID = "100">
<EM ID = "01" Name = "IR01" IsRobot = "TRUE">
<Robot Name = "AR01" Manufacturer = "FANUC" RobotIndex = "1">
<Jobs>
<Job ID = "1" Description = "Handling Step 1" Type = "" />
<Job ID = "2" Description = "Handling Step 2" Type = "" />
<Job ID = "3" Description = "Handling Step 3" Type = "" />
<Job ID = "4" Description = "Handling Step 4" Type = "" />
<Job ID = "5" Description = "Handling Step 5" Type = "" />
<Job ID = "6" Description = "Handling Step 6" Type = "" />
</Jobs>
<Areas>
<Area ID = "1" Description = "100TP01" TargetEM_No = "" />
<Area ID = "2" Description = "100FR02-FX01" TargetEM_No = "" />
</Areas>
<Userbits>
<Userbit ID = "1" Description = "Userbit1: Pick_Action">
<Reference Area = "2" Job = "5" />
</Userbit>
<Userbit ID = "2" Description = "Userbit2: Drop_Action">
<Reference Area = "1" Job = "1" />
<Reference Area = "1" Job = "2" />
<Reference Area = "1" Job = "3" />
<Reference Area = "3" Job = "4" />
<Reference Area = "3" Job = "6" />
</Userbit>
<Userbit ID = "30" Description = "xx_Mute_Sensors">
<Reference Area = "1" Job = "1" />
<Reference Area = "2" Job = "1" />
<Reference Area = "2" Job = "2" />
<Reference Area = "1" Job = "2" />
<Reference Area = "2" Job = "3" />
<Reference Area = "1" Job = "3" />
<Reference Area = "3" Job = "4" />
<Reference Area = "2" Job = "5" />
<Reference Area = "3" Job = "6" />
</Userbit>
<Userbit ID = "31" Description = "xx_Type_Transfer">
<Reference Area = "2" Job = "1" />
<Reference Area = "1" Job = "1" />
<Reference Area = "1" Job = "2" />
<Reference Area = "1" Job = "3" />
<Reference Area = "2" Job = "3" />
<Reference Area = "3" Job = "4" />
<Reference Area = "2" Job = "5" />
<Reference Area = "3" Job = "6" />
</Userbit>
</Userbits>
<FZones />
<Programs>
<Program ID = "1" JobSequence = "1;2;3;4;5;6;" Home = "1" Sheet = "FA01++100+IR01_P1" />
<Program ID = "2" JobSequence = "2;3;4;5;6;" Home = "1" Sheet = "FA01++100+IR01_P1" />
<Program ID = "3" JobSequence = "3;4;5;6;" Home = "1" Sheet = "FA01++100+IR01_P1" />
<Program ID = "4" JobSequence = "4;5;6;" Home = "1" Sheet = "FA01++100+IR01_P1" />
<Program ID = "5" JobSequence = "5;6;" Home = "1" Sheet = "FA01++100+IR01_P1" />
<Program ID = "6" JobSequence = "6;" Home = "1" Sheet = "FA01++100+IR01_P1" />
</Programs>
<Tools>
<Tool ID = "1" Type = "spotweld gun" Name = "FG01" />
<Tool ID = "2" Type = "adhesive gun" Name = "FG02" />
</Tools>
<UserNumbers NumberRequired = "True" />
</Robot>
<TypePlaceholder Name = "" />
</EM>
</Station>
</SA>
<SA ID = "02">
<Station ID = "100">
<EM ID = "02" Name = "IR01" IsRobot = "TRUE">
<Robot Name = "AR02" Manufacturer = "FANUC" RobotIndex = "2">
<Jobs>
<Job ID = "1" Description = "Handling Step 1" Type = "" />
<Job ID = "2" Description = "Handling Step 2" Type = "" />
<Job ID = "3" Description = "Handling Step 3" Type = "" />
<Job ID = "4" Description = "Handling Step 4" Type = "" />
<Job ID = "5" Description = "Handling Step 5" Type = "" />
<Area/>
</Jobs>
<Areas>
<Area ID = "1" Description = "100TP02" TargetEM_No = "" />
<Area ID = "2" Description = "100FR01-FX01" TargetEM_No = "" />
<Area ID = "3" Description = "100FX01" TargetEM_No = "" />
</Areas>
<Userbits>
<Userbit ID = "1" Description = "Userbit1: Pick_Action">
<Reference Area = "2" Job = "4" />
</Userbit>
<Userbit ID = "2" Description = "Userbit2: Drop_Action">
<Reference Area = "1" Job = "1" />
<Reference Area = "1" Job = "2" />
<Reference Area = "2" Job = "3" />
</Userbit>
<Userbit ID = "30" Description = "xx_Mute_Sensors">
<Reference Area = "2" Job = "1" />
<Reference Area = "1" Job = "1" />
<Reference Area = "1" Job = "2" />
<Reference Area = "2" Job = "2" />
<Reference Area = "2" Job = "3" />
<Reference Area = "2" Job = "4" />
<Reference Area = "3" Job = "5" />
</Userbit>
<Userbit ID = "31" Description = "xx_Type_Transfer">
<Reference Area = "2" Job = "1" />
<Reference Area = "1" Job = "1" />
<Reference Area = "1" Job = "2" />
<Reference Area = "2" Job = "2" />
<Reference Area = "2" Job = "3" />
<Reference Area = "2" Job = "4" />
<Reference Area = "3" Job = "5" />
</Userbit>
</Userbits>
<FZones />
<Programs>
<Program ID = "1" JobSequence = "1;2;3;4;5;" Home = "1" Sheet = "FA01++100+IR02_P1" />
<Program ID = "2" JobSequence = "2;3;4;5;" Home = "1" Sheet = "FA01++100+IR02_P1" />
<Program ID = "3" JobSequence = "3;4;5;" Home = "1" Sheet = "FA01++100+IR02_P1" />
<Program ID = "4" JobSequence = "4;5;" Home = "1" Sheet = "FA01++100+IR02_P1" />
<Program ID = "5" JobSequence = "5;" Home = "1" Sheet = "FA01++100+IR02_P1" />
</Programs>
<Tools>
<Tool ID = "1" Type = "gripper" Name = "FG01" />
</Tools>
<UserNumbers NumberRequired = "True" />
</Robot>
<TypePlaceholder Name = "Type" />
</EM>
<EM ID = "03" Name = "IR03" IsRobot = "TRUE">
<Robot Name = "AR03" Manufacturer = "FANUC" RobotIndex = "3">
<Jobs>
<Job ID = "1" Description = "Tackweld Step 1" Type = "" />
<Job ID = "2" Description = "Tackweld Step 2" Type = "" />
<Job ID = "3" Description = "Tackweld Step 3" Type = "" />
<Job ID = "4" Description = "Tackweld Step 4" Type = "" />
<Job ID = "5" Description = "Tackweld Step 5" Type = "" />
<Job ID = "6" Description = "Tackweld Step 6" Type = "" />
<Job ID = "7" Description = "Tackweld Step7" Type = "" />
</Jobs>
<Areas>
<Area ID = "1" Description = "100FR01-FX01" TargetEM_No = "" />
<Area ID = "2" Description = "100FR02-FX01" TargetEM_No = "" />
</Areas>
<Userbits />
<FZones />
<Programs>
<Program ID = "1" JobSequence = "1;2;3;4;5;6;7;" Home = "1" Sheet = "FA01++100+IR03_P1" />
<Program ID = "2" JobSequence = "2;3;4;5;6;7;" Home = "1" Sheet = "FA01++100+IR03_P1" />
<Program ID = "3" JobSequence = "3;4;5;6;7;" Home = "1" Sheet = "FA01++100+IR03_P1" />
<Program ID = "4" JobSequence = "4;5;6;7;" Home = "1" Sheet = "FA01++100+IR03_P1" />
<Program ID = "5" JobSequence = "5;6;7;" Home = "1" Sheet = "FA01++100+IR03_P1" />
<Program ID = "6" JobSequence = "6;7;" Home = "1" Sheet = "FA01++100+IR03_P1" />
<Program ID = "7" JobSequence = "7;" Home = "1" Sheet = "FA01++100+IR03_P1" />
</Programs>
<Tools>
<Tool ID = "1" Type = "spotweld gun" Name = "GW01" />
</Tools>
<UserNumbers NumberRequired = "False" />
</Robot>
</EM>
</Station>
</SA>
</PLC>
<ImportDocuments>
<HandshakeDocument Name = "DO30011_FA01_Robot_PLC_Handshake_v6" ImportDate = "18/04/2024" />
</ImportDocuments>
</Project>
В качестве примера я добавил полный XML и XSD. Это то, что вы имели ввиду? Ограничение уникальности — единственное ограничение, создающее проблему.





Я не знаю, почему существует разница между процессорами схемы, но я отмечаю, что в вашем ограничении уникальности поле <xs:field xpath = ".//Station/@ID"/> никогда не будет выбирать что-либо при запуске из элемента EM, поэтому оно, вероятно, не делает то, что вы намеревались.
Я считаю, что правило XSD 1.0 заключается в том, что когда одно из полей ничего не выбирает, ограничение уникальности считается выполненным. Однако это та область, в которой процессоры схемы не всегда совместимы на 100%.
Теперь вы предоставили больше информации. В частности, вы дали (неформальное) заявление об ограничении, которое вы пытаетесь обеспечить:
Обратите внимание, что мой XML содержит два элемента Station с идентификатором атрибута = 100. Оба этих элемента имеют дочерний элемент EM с именем атрибута = ИР01. Это не должно быть возможным.
Я не уверен, можно ли это выразить в XSD 1.0. Кажется, вы говорите, что иметь две станции с одинаковым идентификатором - это нормально, при условии, что они имеют непересекающиеся наборы значений для EM/@name.
Проблема в том, что если вы попытаетесь выразить это как ограничение на элементы Station, это потребует выбора неограниченного числа полей, но если вы попытаетесь выразить это как ограничение на элементы EM, это потребует доступа к ../@ID как к одному из поля, участвующие в ограничении, и выбор вверх не допускается.
Но, возможно, я неправильно понял ограничение.
Каков был бы правильный способ сделать это тогда? Должен ли я использовать селектор для перехода к элементу станции. Затем используйте поле xs:field, чтобы найти каждый элемент EM? Потому что, когда я пробую это сделать, он проверяет уникальность только внутри одного и того же элемента станции, а не для всех элементов станции.
Вы правильно поняли ограничение. Возможно иметь два элемента станции с одинаковым идентификатором. Итак, если я правильно вас понял, это ограничение не представляется возможным?
Вы можете выразить это с помощью Schematron и XSLT/XPath 2 или более поздней версии, я думаю, например.
<schema xmlns = "http://purl.oclc.org/dsdl/schematron" queryBinding = "xslt3">
<pattern>
<rule context = "PLC">
<assert
test = "every $station1 in .//Station satisfies
every $station2 in .//Station[not($station1 is .) and $station1/@ID = @ID] satisfies
not($station1/EM/@Name = $station2/EM/@Name)">duplicate Names</assert>
</rule>
</pattern>
</schema>
Или вы можете использовать XSD 1.1 с утверждениями, например. со схемой типа
<?xml version = "1.0" encoding = "UTF-8"?>
<xs:schema xmlns:xs = "http://www.w3.org/2001/XMLSchema"
xmlns:vc = "http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault = "qualified"
vc:minVersion = "1.1">
<xs:element name = "Project">
<xs:complexType>
<xs:sequence>
<xs:element name = "PLC" maxOccurs = "unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name = "Type">
<xs:complexType>
<xs:sequence>
<xs:element name = "TypeDef">
<xs:complexType>
<xs:attribute name = "ID" type = "xs:integer"/>
<xs:attribute name = "Name" type = "xs:string"/>
<xs:attribute name = "Description" type = "xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name = "SA" maxOccurs = "unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name = "Station">
<xs:complexType>
<xs:sequence>
<xs:element name = "EM" maxOccurs = "unbounded">
<xs:complexType>
<xs:attribute name = "ID" type = "xs:integer"/>
<xs:attribute name = "Name" type = "xs:string"/>
<xs:attribute name = "IsRobot" type = "xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name = "ID" type = "xs:integer"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name = "ID" type = "xs:integer"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name = "Name" type = "xs:string"/>
<xs:assert id = "no-duplicate-names"
test = "every $station1 in .//Station satisfies
every $station2 in .//Station[not($station1 is .) and $station1/@ID = @ID] satisfies
not($station1/EM/@Name = $station2/EM/@Name)"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
экземпляр типа
<?xml version = "1.0" encoding = "UTF-8"?>
<Project>
<PLC Name = "PLC">
<Type>
<TypeDef ID = "1" Name = "G05" Description = "" />
</Type>
<SA ID = "01">
<Station ID = "100">
<EM ID = "01" Name = "IR01" IsRobot = "TRUE"></EM>
</Station>
</SA>
<SA ID = "02">
<Station ID = "100">
<EM ID = "02" Name = "IR04" IsRobot = "TRUE"></EM>
<EM ID = "03" Name = "IR03" IsRobot = "TRUE"></EM>
</Station>
</SA>
</PLC>
</Project>
должен быть действительным, пока экземпляр типа
<?xml version = "1.0" encoding = "UTF-8"?>
<Project>
<PLC Name = "PLC">
<Type>
<TypeDef ID = "1" Name = "G05" Description = "" />
</Type>
<SA ID = "01">
<Station ID = "100">
<EM ID = "01" Name = "IR01" IsRobot = "TRUE"></EM>
</Station>
</SA>
<SA ID = "02">
<Station ID = "100">
<EM ID = "02" Name = "IR01" IsRobot = "TRUE"></EM>
<EM ID = "03" Name = "IR03" IsRobot = "TRUE"></EM>
</Station>
</SA>
</PLC>
</Project>
недействителен (и, например, SaxonEE сообщит вам
Validation error on line 3 column 21 of names-invalid.xml:
FORG0001: Element PLC does not satisfy assertion every $station1 in .//Station satisfies
every $station2 in .//Station[not($station1 is .) and $station1/@ID = @ID] satisfies
not($station1/EM/@Name = $station2/EM/@Name)
See https://www.w3.org/TR/xmlschema11-1/#sec-cvc-assertion clause 0
Nodes for which the assertion fails:
* element(Station) at PLC/SA[1]/Station[1]
* element(Station) at PLC/SA[2]/Station[1]
)
XSD 1.1 поддерживается как минимум двумя библиотеками с открытым исходным кодом (Apache Xerces Java https://xerces.apache.org/xerces2-j/ , Python XMLSchema https://pypi.org/project/xmlschema/) и различные коммерческие библиотеки, такие как SaxonEE или AltovaXML.
Пример консольного приложения .NET 8, использующего библиотеку Python XmlSchema с пакетом PythonNet, доступен по адресу https://github.com/martin-honnen/PythonNETXmlSchemaTest1.
Спасибо за ваш ответ! У меня возникли проблемы с размещением правила xs:assert. Я получаю сообщение об ошибке: элемент не поддерживается в этом контексте. Я поместил его в комплекс элемента "ПЛК". Есть идеи, что это может быть? Я пробовал переносить его на разные сложные типы, но не могу заставить его работать.
@MaartenSchuurmans, я думаю, проблема в основном в том, что вы предполагаете, что утверждение работает с любым процессором схемы, например с процессором .NET от Microsoft. Но утверждения были введены в последней версии XSD 1.1 XSD, это было много лет назад, но, к сожалению, многие процессоры/валидаторы схемы XSD 1.0, такие как Microsoft, никогда не обновлялись для поддержки XSD 1.1. Таким образом, вам в основном придется переключиться на другой стек, что осложняется тем фактом, что Saxon EE для .NET является коммерческим, а другие варианты (с открытым исходным кодом) находятся на Java или Python, поэтому для использования из .NET вам понадобится IKVM или Python. мост.
@MaartenSchuurmans, я добавил ссылку на образец консольного приложения .NET 8, которое использует пакет NuGet pythonnet для выполнения проверки XSD 1.1 с помощью библиотеки Python XmlSchema с открытым исходным кодом.
Предоставьте исполняемый файл: полную схему и исходный документ, демонстрирующий проблему. (Например, очень важно, где в вашей схеме появляется ограничение
xs:unique). Также: обнаруживает ли ваш код C# другие ошибки проверки или проблемы возникают только из-за ограничения уникальности?