XSD-어떤 순서로든 여러 번 요소를 허용하는 방법은 무엇입니까?


109

XSD를 만들고 다음 요구 사항으로 정의를 작성하려고합니다.

  • 지정된 하위 요소가 여러 번 표시되도록 허용 (0에서 제한 없음)
  • 자식 요소의 순서에 관계없이 허용

나는 주위를 둘러 보았다과 같은 다양한 솔루션 발견 :

<xs:element name="foo">
  <xsl:complexType>
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="child1" type="xs:int"/>
      <xs:element name="child2" type="xs:string"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

그러나 내가 이해하는 바에서 xs : choice는 여전히 단일 요소 선택 만 허용합니다. 따라서 MaxOccurs를 이와 같이 제한되지 않음으로 설정하면 자식 요소 중 "하나"가 여러 번 나타날 수 있음을 의미합니다. 정확합니까?

위의 해결 방법이 잘못된 경우 요구 사항에서 위에서 언급 한 내용을 어떻게 얻을 수 있습니까?

편집 : 요구 사항이 다음과 같으면 어떻게합니까?

  • element child1 child2는 여러 번 나타날 수 있습니다 (0에서 제한 없음).
  • 순서에 관계없이 요소
  • child3 및 child4 요소는 정확히 한 번 표시되어야합니다.

예를 들어 다음 xml은 유효합니다.

<foo>
<child1> value </child1>
<child1> value </child1>
<child3> value </child3>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>

그러나 이것은 아닙니다 (missing child3)

<foo>
<child1> value </child1>
<child1> value </child1>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>

답변:


61

스키마에서 질문에 child1있거나 child2임의의 순서로 여러 번 나타날 수 있습니다. 그래서 이것은 당신이 찾고있는 것 같습니다.

편집 : 그중 하나만 무제한으로 나타나게하려면 제한되지 않은 요소가 대신 요소로 이동해야합니다.

편집 : XML의 고정 유형.

편집 : maxOccurs에서 대문자 O

<xs:element name="foo">
   <xs:complexType>
     <xs:choice maxOccurs="unbounded">
       <xs:element name="child1" type="xs:int" maxOccurs="unbounded"/>
       <xs:element name="child2" type="xs:string" maxOccurs="unbounded"/>
     </xs:choice>
   </xs:complexType>
</xs:element>

기본적으로 그렇습니다. 저는 child1, child2 요소가 순서에 관계없이 몇 번이나 나타나고 있는지 찾고 있습니다. 여기에 제공 한 답변은 단일 요소에만 적용됩니다. 아니면 내 요구 사항도 해결됩니까?
jvtech

질문의 스키마가 요구 사항을 충족합니다. 내 대답의 대체 스키마는 단일 요소에 대한 것입니다. 그것이 해결되기를 바랍니다! :)
xcut

@Pavel, @xcut, 설명해 주셔서 감사합니다. 편집 된 요구 사항을 참조하십시오.
jvtech

2
jvtech : XML 스키마로 편집 된 요구 사항을 충족 할 수 없습니다. 이를 달성하는 유일한 방법은 child3 및 child4가 끝에 만 나타날 수있는 경우입니다. 어떤 경우에는 선택 항목과 두 요소를 포함하는 시퀀스가 ​​필요합니다.
xcut 2010

1
@ Daij-Djan 나는 또한 그것이 작동하지 않는다는 것을 발견했습니다. 하나 이상의 하위 요소가 허용되도록 선택 요소에 maxOccurs = "unbounded"를 추가해보십시오.
MikeD 2015 년

107

나중에 편집 할 때 추가 된 질문의 대체 공식은 아직 답이없는 것 같습니다. 요소의 자식 사이에 명명 된 child3, 명명 된 child4, 명명 된 번호 , child1또는 명명 된 번호 가 있어야하며 child2순서에 대한 제약없이 지정 하는 방법 아이들이 나타납니다.

이것은 간단하게 정의 할 수있는 정규 언어이며 필요한 콘텐츠 모델은 숫자 '3'과 '4'가 각각 정확히 한 번 발생하고 숫자 '1'과 '2가 나오는 문자열 세트를 정의하는 정규 표현식과 동형입니다. '는 여러 번 발생합니다. 이것을 작성하는 방법이 분명하지 않다면 그러한 언어를 인식하기 위해 어떤 종류의 유한 상태 머신을 구축 할 것인지 생각하는 것이 도움이 될 수 있습니다. 최소한 네 가지 상태가 있습니다.

  • '3'도 '4'도 보이지 않는 초기 상태
  • '3'은 보이지만 '4'는 보이지 않는 중간 상태
  • '4'는 보이지만 '3'은 보이지 않는 중간 상태
  • '3'과 '4'가 모두 보이는 최종 상태

자동 장치가 어떤 상태에 있든 '1'과 '2'를 읽을 수 있습니다. 그들은 기계의 상태를 변경하지 않습니다. 초기 상태에서는 '3'또는 '4'도 허용됩니다. 중간 상태에서는 '4'또는 '3'만 허용됩니다. 최종 상태에서는 '3'도 '4'도 허용되지 않습니다. 정규식의 구조는 '3'과 '4'만 발생하는 언어의 하위 집합에 대한 정규식을 먼저 정의하면 이해하기 가장 쉽습니다.

(34)|(43)

'1'또는 '2'가 주어진 위치에서 여러 번 발생하도록 허용하려면 삽입 할 수 있습니다 (1|2)*(또는 [12]*정규식 언어가 해당 표기법을 허용하는 경우). 사용 가능한 모든 위치에이 표현식을 삽입하면

(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*

이것을 콘텐츠 모델로 번역하는 것은 간단합니다. 기본 구조는 정규식과 동일합니다 (34)|(43).

<xsd:complexType name="paul0">
  <xsd:choice>
    <xsd:sequence>
      <xsd:element ref="child3"/>
      <xsd:element ref="child4"/>
    </xsd:sequence>
    <xsd:sequence>
      <xsd:element ref="child4"/>
      <xsd:element ref="child3"/>
    </xsd:sequence>
  </xsd:choice>
</xsd:complexType>

의 제로 또는-더 많은 선택 삽입 child1하고하는 것은 child2간단합니다 :

<xsd:complexType name="paul1">
  <xsd:sequence>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
  </xsd:sequence>
</xsd:complexType>

벌크를 약간 최소화하려면 child1및 반복 선택에 대해 명명 된 그룹을 정의 할 수 있습니다 child2.

<xsd:group name="onetwo">
  <xsd:choice>
    <xsd:element ref="child1"/>
    <xsd:element ref="child2"/>
  </xsd:choice>   
</xsd:group>

<xsd:complexType name="paul2">
  <xsd:sequence>
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>  
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

XSD 1.1에서는 all-groups 에 대한 일부 제약 이 해제되었으므로이 콘텐츠 모델을보다 간결하게 정의 할 수 있습니다.

<xsd:complexType name="paul3">
  <xsd:all>
    <xsd:element ref="child1" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child2" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child3"/>
    <xsd:element ref="child4"/>      
  </xsd:all>
</xsd:complexType>

그러나 이전에 주어진 예에서 볼 수 있듯이 all그룹에 대한 이러한 변경 은 실제로 언어의 표현력을 변경하지 않습니다. 특정 언어의 정의를 더 간결하게 만들뿐입니다.


3
나는 XSD 1.0 xs : all 대안을 좋아합니다.
TWiStErRob

8
+1. 이것은 훌륭한 답변이며 더 많은 찬성 투표를 할 가치가 있습니다.
Christoffer Lette

1
좋은 대답! 이런 설명이 정말 좋아요. 목표 달성의 모든 논리와 추론을 보여줍니다. 이제 저는이 문제를 해결하는 방법을 알뿐만 아니라 비슷한 문제를 해결하는 새로운 접근 방식을 배웠습니다. 유한 상태 자동화를 사용하여 이것을 설명하는 것은 매우 좋은 생각입니다.
egelev 2014-02-27

3
마이클, 당신은 "모든 그룹에 대한 이러한 변화는 실제로 언어의 표현력을 변경하지 않습니다. 그들은 단지 특정 종류의 언어의 정의를 더 간결하게 만듭니다"라고 말합니다. 그러나 문제를 여러 하위 요소로 일반화하면 하위 요소의 하위 집합은 한 번 나타날 수 있고 다른 하위 요소는 여러 번 나타날 수 있습니다. XSD 1.0 솔루션은 조합 폭발을 일으킬 것입니다. XSD 1.1 솔루션은 깨끗하게 유지됩니다.
ebruchez

1
ebruchez, 예 - 표현력은 내가 용어를 사용할 때, 동일하지 않습니다 간결 , 컴팩트 , 간결성 , 또는 관리 . 표현력은 "이 형식주의가이 언어를 정의 할 수 있는가?" 문법의 크기 나 문법적 설탕이 문법을 더 작게 만들지 여부를 묻지 않습니다. 당신이 언급 한 조합 적 폭발은 모든 그룹에 대한 XSD 1.1 변경없이 많은 요소 세트를 처리하는 것이 매우 불쾌하다는 것을 의미합니다 (그리고 큰 n의 경우 메모리가 소모 될 수 있음). 원칙적으로 불가능하다는 의미는 아닙니다.
CM Sperberg-McQueen

49

이것이 마침내 나를 위해 일한 것입니다.

<xsd:element name="bar">
  <xsd:complexType>
    <xsd:sequence>
      <!--  Permit any of these tags in any order in any number     -->
      <xsd:choice minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="child1" type="xsd:string" />
        <xsd:element name="child2" type="xsd:string" />
        <xsd:element name="child3" type="xsd:string" />
      </xsd:choice>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

5
실제로 트릭은 한정 기호와 함께 xsd : choice를 사용하는 것입니다. <xsd : choice minOccurs = "0"maxOccurs = "unbounded">
tivo

6
위의 예제는 선택 요소를 둘러싸는 시퀀스 요소 없이도 작동한다는 점을 지적 할 가치가 있다고 생각합니다.

9

그러나 내가 이해하는 바에서 xs : choice는 여전히 단일 요소 선택 만 허용합니다. 따라서 MaxOccurs를 이와 같이 제한되지 않음으로 설정하면 자식 요소 중 "하나"가 여러 번 나타날 수 있음을 의미합니다. 정확합니까?

아니요. 선택 xs:choice은로 인해 발생하는 모든 "반복"에 대해 개별적으로 발생합니다 maxOccurs="unbounded". 따라서 게시 한 코드는 정확하며 실제로 작성한대로 원하는 작업을 수행합니다.


@Alan이 제공 한 답변에 대한 귀하의 의견은 모두 잘 설명합니다.
bor

3

다음 스키마가 제안한 내용을 허용한다는 것을 알 수 있습니다.

  <xs:element name="foo">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:choice>
          <xs:element maxOccurs="unbounded" name="child1" type="xs:unsignedByte" />
          <xs:element maxOccurs="unbounded" name="child2" type="xs:string" />
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

이렇게하면 다음과 같은 파일을 만들 수 있습니다.

<?xml version="1.0" encoding="utf-8" ?>
<foo>
  <child1>2</child1>
  <child1>3</child1>
  <child2>test</child2>
  <child2>another-test</child2>
</foo>

귀하의 질문과 일치하는 것 같습니다.


minOccursmaxOccurs하위 항목은 1 개로 제한됩니다 xs:all.
Pavel Minaev

파벨 : 다음 내 게시물을 확인하는 더블과는 XS를 제거하기를 편집 한 후 덕분에 ... 나는이 밖으로 발견 : 모든
Steven_W

1

위의 어느 것도 작동하지 않는 경우 HIPPA 스키마 또는 기타 복잡한 xsd에 대해 결과를 검증해야하는 EDI 추적 작업을 수행하고있을 것입니다. 요구 사항은 8 개의 REF 세그먼트가 있고 그 중 하나가 임의의 순서로 나타나야하고 모두가 필수는 아니라는 것입니다. 즉, 1st REF, 3rd REF, 2nd REF, 9th REF 순서대로 가질 수 있습니다. 기본 상황에서는 EDI 수신이 실패합니다. 기본 복합 유형은 다음과 같습니다.

<xs:sequence>
  <xs:element.../>
</xs:sequence>

굴절에 의해 요소를 호출 할 때 상황은 심지어 복잡하고 원래 지점의 요소 자체가 매우 복잡합니다. 예를 들면 :

<xs:element>
<xs:complexType>
<xs:sequence>
<element name="REF1"  ref= "REF1_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF2"  ref= "REF2_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF3"  ref= "REF3_Mycustomelment" minOccurs="0" maxOccurs="1">
</xs:sequence>
</xs:complexType>
</xs:element>

해결책:

여기서 단순히 "sequence"를 "all"로 바꾸거나 "choice"를 최소 / 최대 조합으로 사용하는 것은 작동하지 않습니다!

먼저 대체 "xs:sequence" with "<xs:all>" 요소를 참조하는 위치를 변경해야합니다.

<xs:annotation>
  <xs:appinfo>
    <b:recordinfo structure="delimited" field.........Biztalk/2003">

*** 이제 위의 세그먼트에서 다음과 같이 마지막에 트리거 지점을 추가합니다. trigger_field = "REF01 _... complete name .."trigger_value = "38" "18"과 같이 트리거 값이 다른 다른 REF 세그먼트에 대해서도 동일하게 수행합니다. ","XX ","YY "등. 이제 레코드 정보가 다음과 같이 표시됩니다.b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">


이렇게하면 각 요소가 고유하게됩니다. 이유는 모든 REF 세그먼트 (위 예)가 REF01, REF02, REF03과 같은 구조를 갖기 때문입니다. 그리고 유효성 검사 중에 구조 유효성 검사는 괜찮지 만 첫 번째 REF 자체에서 나머지 값을 찾으려고하기 때문에 값이 반복되지 않도록합니다. 트리거를 추가하면 모두 고유하게 만들어지며 모든 순서와 상황에 따라 전달됩니다 (예 : 9/9가 아닌 5/9 사용).

나는 이것에 거의 20 시간을 보냈기 때문에 도움이되기를 바랍니다.

행운을 빕니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.