Вы можете иметь более одного индикатора в сложном элементе XSD? - PullRequest
0 голосов
/ 04 мая 2020

Я пытаюсь создать новую схему для проверки XML по моей работе. Но я с трудом отвечаю на вопрос: могу ли я и как создать сложный элемент, который имеет некоторые элементы, которые должны быть в заданной последовательности, а другие подэлементы - нет? В конечном итоге я думаю, что у меня должна быть возможность открывать и закрывать теги «sequence», а также открывать и закрывать теги «all» вокруг двух наборов элементов, но xsd, похоже, не нравится. Вот что у меня есть:

<xsd:complexType name="Original">
        <xsd:sequence>
            <xsd:element maxOccurs="1" minOccurs="1" name="AssetIdentifier" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation>Definition: The Asset Identifier element is intended to
                        reflect the root of all following digital filenames.</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            <xsd:element maxOccurs="1" minOccurs="0" name="ArchiveID" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation>Definition: The Filename element in this section is
                        intended to reflect the root of all the following derivative digital
                        filenames.</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            <xsd:element maxOccurs="1" minOccurs="1" name="Title" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation>Definition: The known title of the asset. If no title is
                        known, one can be assigned; a number or letter sequence, whichever is
                        the most logical. Using the value "unknown" is also
                        acceptable.</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            <xsd:element maxOccurs="1" minOccurs="1" name="RecordDate" type="xsd:date">
                <xsd:annotation>
                    <xsd:documentation>Definition: The actual recording date of the asset.
                        Estimates, partial dates, and date ranges (i.e. 19XX, Feb. 19-24,
                        1934-1935, etc.) are allowable, as is 'unknown'. Best practice, when
                        applicable, is to use the YYYY-MM-DD format in accordance with ISO 8601.
                        Even partial dates, i.e. 1990-05 should adhere to this
                        format.</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            <xsd:element maxOccurs="1" minOccurs="1" name="FormatType" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation>Definition: The format of the analog asset, i.e. Open
                        Reel, Grooved Disc, DAT, Cassette, VHS, 16mm film, EIAJ,
                        etc.</xsd:documentation>
                    <xsd:documentation>Best Practice: The MediaPreserve maintains a list of
                        controlled vocabularies organized by media type at: www.dontknowyet.com.
                        However, MP opted to meake this an unrestricted element in the event
                        that other ogranizations have their own controlled vocabularies in
                        place.</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
         </xsd:sequence>
        <xsd:all>
            <xsd:element maxOccurs="1" minOccurs="0" name="StockBrand" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation>If known definitively</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            <xsd:element maxOccurs="1" minOccurs="0" name="TapeModel" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation>If applicable. Usually applies to DAT tapes, open reels,
                        and wire recordings.</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
            <xsd:element maxOccurs="1" minOccurs="0" name="TapeWidth" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation>Typically only applicable for open reel
                        audio</xsd:documentation>
                </xsd:annotation>
            </xsd:element>
        </xsd:all>

1 Ответ

0 голосов
/ 06 мая 2020
К сожалению,

XSD не разрешают то, что вы пытаетесь сделать (объедините <sequence/> и <all /> внутри одного сложного типа или элемента). Возможно, вам удастся добиться чего-то похожего с моделью вложенного контента, но учтите, что вы не можете вкладывать <all>, кроме как под другим <all />, в противном случае вы должны определить это в другом элементе. Однако вы можете вкладывать либо <sequence>, либо <choice> друг в друга.

Из моего понимания XSD у вас есть 3 жизнеспособных варианта.

Во-первых, вложите все элементы, которые вы хотите в <all />, в свои собственные подэлементы:

<xs:complexType name="Original">
  <xs:sequence>
    <!-- AssetIdentifier to FormatType left out for brevity -->
    <xs:element name="Misc">
      <xs:complexType>
        <xs:all>
          <xs:element maxOccurs="1" minOccurs="0" name="StockBrand" type="xs:string" />
          <xs:element maxOccurs="1" minOccurs="0" name="TapeModel" type="xs:string" />
          <xs:element maxOccurs="1" minOccurs="0" name="TapeWidth" type="xs:string" />
        </xs:all>
      </xs:complexType>
    </xs:element>
  </xs:sequence>
</xs:complexType>
<!-- For the above, valid XML would be: -->
<Original>
  <AssetIdentifier>AssetIdentifier0</AssetIdentifier>
  <Title>Title0</Title>
  <RecordDate>2006-05-04</RecordDate>
  <FormatType>FormatType0</FormatType>
  <Misc>
    <!-- Optional & order doesn't matter -->
    <StockBrand>what</StockBrand>
    <TapeWidth>1290</TapeWidth>
    <TapeModel>Hey</TapeModel>
  </Misc>
</Original>

Во-вторых, вложите эти элементы в другой <sequence /> , что позволяет go указать другой подэлемент, но теперь требует, чтобы элементы отображались в порядке, указанном в схеме. Обратите внимание, что сама вложенная последовательность может быть необязательной.

<xs:complexType name="Original">
  <xs:sequence>
    <!-- AssetIdentifier to FormatType left out for brevity -->
    <xs:sequence minOccurs="0">
      <xs:element maxOccurs="1" minOccurs="0" name="StockBrand" type="xs:string" />
      <xs:element maxOccurs="1" minOccurs="0" name="TapeModel" type="xs:string" />
      <xs:element maxOccurs="1" minOccurs="0" name="TapeWidth" type="xs:string" />
    </xs:sequence>
  </xs:sequence>
</xs:complexType>

<!-- For the above, valid XML would be: -->
<Original>
  <AssetIdentifier>AssetIdentifier0</AssetIdentifier>
  <Title>Title0</Title>
  <RecordDate>2006-05-04</RecordDate>
  <FormatType>FormatType0</FormatType>
  <!-- Optional below, but must be ordered -->
  <StockBrand>what</StockBrand>
  <TapeModel>Hey</TapeModel>
  <TapeWidth>1290</TapeWidth>
</Original>

Существует третий вариант, который немного "взломан", но все же позволяет указывать элементы go неупорядоченным, все еще остается необязательным, но все еще появляется рядом с другими обязательными, упорядоченными элементами. Это вложит выбор (с maxOccurs = "3" ) в последовательности, внутри родительской последовательности (sequence> sequence> choice):

<xs:complexType name="Original">
  <xs:sequence>
    <!-- AssetIdentifier to FormatType left out for brevity -->
    <xs:sequence>
      <xs:choice maxOccurs="3" minOccurs="0">
        <xs:element name="StockBrand" type="xs:string"/>
        <xs:element name="TapeModel" type="xs:string"/>
        <xs:element name="TapeWidth" type="xs:string"/>
      </xs:choice>
    </xs:sequence>
  </xs:sequence>
</xs:complexType>
<!-- For the above, valid XML would be: -->
<Original>
  <AssetIdentifier>AssetIdentifier0</AssetIdentifier>
  <Title>Title0</Title>
  <RecordDate>2006-05-04</RecordDate>
  <FormatType>FormatType0</FormatType>
  <!-- Optional, unordered, but there's a catch: -->
  <TapeWidth>1290</TapeWidth>
  <StockBrand>what</StockBrand>
  <TapeModel>Hey</TapeModel>
</Original>

Однако с этим 3-м вариантом есть подвох maxOccurs="3" на элементе <choice /> делает minOccurs и maxOccurs на дочерних элементах (StockBrand, TapeModel и TapeWidth) бессмысленными; это означает, что эти элементы, оставаясь необязательными, теперь могут появляться более одного раза, при условии, что совокупное количество элементов по-прежнему равно 3 или менее:

Это становится действительным (2 из того же элемента + еще 1) :

  <TapeWidth>1290</TapeWidth>
  <TapeWidth>1291</TapeWidth>
  <TapeModel>Hey</TapeModel>

И это все еще действует (3 одинаковых):

  <TapeWidth>1290</TapeWidth>
  <TapeWidth>1291</TapeWidth>
  <TapeWidth>1292</TapeWidth>

И также это (только 1 вхождение 1 элемента):

  <StockBrand>1290</StockBrand>

Возможно, вы могли бы попытаться найти другой вариант, поигравшись с сочетанием последовательности и вложенности выбора, но лучше всего сохранять свои схемы простыми. Лично я бы порекомендовал первые 2 варианта, а не третий, чтобы ваша схема была простой.

...