Как смоделировать отношения N-N-N в XML без дублирования данных или введения строковых дескрипторов? - PullRequest
1 голос
/ 22 июня 2011

Я пытаюсь получить структуру XML, эквивалентную этой:

<worker>
<name>Adam</name>
<project>
<name>Foo</name>
</project>
<project>
<name>Bar</name>
</project>
</worker>
<worker>
<name>Eve</name>
<project>
<name>Foo</name>
</project>
</worker>
<worker>
<name>Lizzie</name>
<project>
<name>Bar</name>
</project>
</worker>

, но без дублирования содержимого тега.Как я могу ввести ссылки между проектами и работниками таким образом, который будет проверен парсером, и как будет выглядеть требуемый файл .xsd?

Ответы [ 3 ]

1 голос
/ 22 июня 2011

XSD поддерживает отношения идентичности через keyref и ключевые элементы .Я собирался придумать пример, но обнаружил, , этот хорошо его охватывает .Я скопировал образец ниже.Обратите внимание, что у каждого item есть @number, что соответствует product в разделе products документа.Это применяется в xsd через определение OrderType.

<order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="chapter17.xsd">
  <number>123ABBCC123</number>
  <items>
    <shirt number="557">
      <quantity>1</quantity>
      <color value="blue"/>
    </shirt>
    <shirt number="557">
      <quantity>1</quantity>
      <color value="sage"/>
    </shirt>
    <hat number="563">
      <quantity>1</quantity>
    </hat>
  </items>
  <products>
    <product>
      <number>557</number>
      <name>Short-Sleeved Linen Blouse</name>
      <price currency="USD">29.99</price>
    </product>
    <product>
      <number>563</number>
      <name>Ten-Gallon Hat</name>
      <price currency="USD">69.99</price>
    </product>
  </products>
</order>


<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="order" type="OrderType">
    <xs:keyref name="prodNumKeyRef" refer="prodNumKey">
      <xs:selector xpath="items/*"/>
      <xs:field xpath="@number"/>
    </xs:keyref>
    <xs:key name="prodNumKey">
      <xs:selector xpath=".//product"/>
      <xs:field xpath="number"/>
    </xs:key>
  </xs:element>

  <xs:complexType name="OrderType">
    <xs:sequence>
      <xs:element name="number" type="xs:string"/>
      <xs:element name="items" type="ItemsType"/>
      <xs:element name="products" type="ProductsType"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="ItemsType">
    <xs:choice maxOccurs="unbounded">
      <xs:element name="shirt" type="ProductOrderType"/>
      <xs:element name="hat" type="ProductOrderType"/>
    </xs:choice>
  </xs:complexType>

  <xs:complexType name="ProductOrderType">
    <xs:sequence>
      <xs:element name="quantity" type="xs:integer"/>
      <xs:element name="color" type="ColorType" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="number" type="xs:integer"/>
  </xs:complexType>

  <xs:complexType name="ProductsType">
    <xs:sequence>
      <xs:element name="product" type="ProductType"
                   maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="ProductType">
    <xs:sequence>
      <xs:element name="number" type="xs:integer"/>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="price" type="PriceType"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="ColorType">
    <xs:attribute name="value" type="xs:string"/>
  </xs:complexType>

  <xs:complexType name="PriceType">
    <xs:simpleContent>
      <xs:extension base="xs:decimal">
        <xs:attribute name="currency" type="xs:token"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

</xs:schema>
0 голосов
/ 22 июня 2011

Я думаю, что есть три основных способа моделирования отношений между работником и проектом. Может быть иерархическим по проекту:

<project name="X">
  <worker name="Sue"/>
  <worker name="John"/>
</project>
<project name="Y">
  <worker name="Sue"/>
  <worker name="Bill"/>
</project>

или иерархия по работнику:

<worker name="Sue">
  <project name="X"/>
  <project name="Y"/>
</worker>

или квартира:

<engagement project="X" worker="Sue"/>
<engagement project="Y" worker="Bill"/>

Во всех трех случаях, если вы хотите избежать дублирования данных, вам нужны внешние ключи (например, значения IDREF) для связи с элементами, содержащими сведения о проекте или работнике.

Какой из трех вы выбираете, полностью зависит от вас. Очень часто вы будете переходить из одного представления в другое, поэтому группировка в XSLT так важна - она ​​часто используется для такого рода иерархической инверсии.

0 голосов
/ 22 июня 2011

Вы можете создать отношения в наборе данных, а затем создать схему из этого.Я расширил пример из моего блога здесь: http://weblogs.asp.net/stevewellens/archive/2009/01/05/create-an-xsd-schema-without-knowing-a-damn-thing-about-xsd.aspx

DataSet MyDataSet = new DataSet("MyDataSet");

// This can be confusing, the 'DataTable' will actually
// become Elements (Rows) in the XML file.

DataTable GolferDataTable = new DataTable("Golfer");
DataTable CourseDataTable = new DataTable("Course");
DataTable MemberShipDataTable = new DataTable("Members");

MyDataSet.Tables.Add(GolferDataTable);
MyDataSet.Tables.Add(CourseDataTable);
MyDataSet.Tables.Add(MemberShipDataTable);        

// Make columns attributes so we can 
// link directly to a GridView
GolferDataTable.Columns.Add(new DataColumn("GolferID",
                             typeof(System.Int32),
                             null,
                             MappingType.Attribute));

GolferDataTable.Columns.Add(new DataColumn("GolferName",
                             typeof(String),
                             null,
                             MappingType.Attribute));

CourseDataTable.Columns.Add(new DataColumn("CourseID",
                              typeof(System.Int32),
                              null,
                              MappingType.Attribute));

CourseDataTable.Columns.Add(new DataColumn("CourseName",
                             typeof(String),
                             null,
                             MappingType.Attribute));

MemberShipDataTable.Columns.Add(new DataColumn("CourseID",
                              typeof(System.Int32),
                              null,
                              MappingType.Attribute));

MemberShipDataTable.Columns.Add(new DataColumn("GolferID",
                              typeof(System.Int32),
                              null,
                              MappingType.Attribute));

DataRelation Relation1 = new DataRelation("Members1", MemberShipDataTable.Columns["GolferID"], GolferDataTable.Columns["GolferID"]);
DataRelation Relation2 = new DataRelation("Members2", MemberShipDataTable.Columns["CourseID"], CourseDataTable.Columns["CourseID"]);

MyDataSet.Relations.Add(Relation1);
MyDataSet.Relations.Add(Relation2);

// Write out the XSD
MyDataSet.WriteXmlSchema(@"C:\GolfersSchema.xsd");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...