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 ให้ไม่ถูกผูกไว้เช่นนี้ควรหมายความว่า "รายการใดรายการหนึ่ง" ขององค์ประกอบลูกสามารถปรากฏได้หลายครั้งเท่านั้น นี่คือความถูกต้อง?

หากวิธีแก้ปัญหาข้างต้นไม่ถูกต้องฉันจะบรรลุสิ่งที่ระบุไว้ข้างต้นในข้อกำหนดของฉันได้อย่างไร?

แก้ไข : จะเกิดอะไรขึ้นหากข้อกำหนดเป็นดังนี้

  • องค์ประกอบ 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>

แต่นี่ไม่ใช่ (ไม่มีเด็ก 3)

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

คำตอบ:


62

ในสคีมาที่คุณมีคำถามchild1หรือchild2สามารถปรากฏในลำดับใดก็ได้กี่ครั้งก็ได้ ดูเหมือนว่าคุณกำลังมองหาอะไรอยู่

แก้ไข:หากคุณต้องการให้เพียงหนึ่งในนั้นปรากฏโดยไม่ จำกัด จำนวนครั้งสิ่งที่ไม่ถูกผูกไว้จะต้องไปที่องค์ประกอบแทน:

แก้ไข:ประเภทคงที่ใน XML

แก้ไข:ตัวพิมพ์ใหญ่ O ใน maxOccurs

<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 schema; วิธีเดียวที่จะบรรลุได้ก็คือถ้า child3 และ child4 สามารถปรากฏในตอนท้ายเท่านั้น ในกรณีนี้คุณต้องมีลำดับที่มีตัวเลือกและองค์ประกอบทั้งสอง
xcut

1
@ Daij-Djan ฉันยังพบว่ามันไม่ได้ผล ลองเพิ่ม maxOccurs = "unbounded" ในองค์ประกอบทางเลือกเพื่อให้อนุญาตให้มีองค์ประกอบลูกมากกว่าหนึ่งรายการ
MikeD

107

การกำหนดทางเลือกของคำถามที่เพิ่มในการแก้ไขในภายหลังดูเหมือนจะยังไม่ได้รับคำตอบ: วิธีระบุว่าในกลุ่มย่อยขององค์ประกอบจะต้องมีชื่อchild3หนึ่งชื่อchild4และหมายเลขใด ๆ ที่มีชื่อchild1หรือchild2โดยไม่มีข้อ จำกัด ในลำดับใน ซึ่งเด็ก ๆ ปรากฏตัว

นี่เป็นภาษาปกติที่กำหนดได้อย่างตรงไปตรงมาและรูปแบบเนื้อหาที่คุณต้องการคือ isomorphic สำหรับนิพจน์ทั่วไปที่กำหนดชุดของสตริงซึ่งแต่ละหลัก '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]*ถ้าภาษา regex ของเรายอมรับสัญกรณ์นั้น) เราได้รับการแทรกนิพจน์นี้ในตำแหน่งที่มีอยู่ทั้งหมด

(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กลุ่มได้ถูกยกออกไปดังนั้นจึงเป็นไปได้ที่จะกำหนดรูปแบบเนื้อหานี้ให้รัดกุมยิ่งขึ้น:

<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-groups เหล่านี้ไม่ได้เปลี่ยนพลังในการแสดงออกของภาษา ทำให้คำจำกัดความของภาษาบางประเภทมีความกระชับมากขึ้นเท่านั้น


3
ฉันชอบ XSD 1.0 xs: ทางเลือกทั้งหมด
TWiStErRob

8
+1. นี่เป็นคำตอบที่ยอดเยี่ยมและสมควรได้รับคะแนนโหวตมากขึ้น
Christoffer Lette

1
ตอบโจทย์มาก! ฉันชอบคำอธิบายแบบนี้มาก เผยให้เห็นตรรกะและเหตุผลเบื้องหลังการบรรลุเป้าหมาย ตอนนี้ฉันไม่เพียง แต่รู้วิธีแก้ปัญหานี้ แต่ฉันได้เรียนรู้แนวทางใหม่ในการแก้ปัญหาที่คล้ายกัน การอธิบายเรื่องนี้โดยใช้ระบบอัตโนมัติแบบ จำกัด สถานะเป็นความคิดที่ดีมาก
egelev

3
ไมเคิลคุณพูดว่า "การเปลี่ยนแปลงเหล่านี้กับคนทุกกลุ่มในความเป็นจริงไม่ได้เปลี่ยนพลังในการแสดงออกของภาษา แต่เพียง แต่ทำให้คำจำกัดความของภาษาบางประเภทกระชับขึ้นเท่านั้น" แต่ถ้าคุณสรุปปัญหาให้กับองค์ประกอบลูกจำนวนเท่าใดก็ได้ชุดย่อยที่สามารถปรากฏขึ้นครั้งเดียวและชุดย่อยอื่นที่สามารถปรากฏขึ้นกี่ครั้งก็ได้โซลูชัน XSD 1.0 จะทำให้เกิดการระเบิดร่วมกันใช่หรือไม่ แม้ว่าโซลูชัน XSD 1.1 จะยังคงสะอาด
ebruchez

1
ebruchez ใช่ - แสดงพลังที่ผมใช้คำว่าไม่ได้เป็นเช่นเดียวกับความกระชับ , แน่น , รวบรัดหรือการบริหารจัดการ พลังที่แสดงออกเพียงถามว่า "พิธีการนี้กำหนดภาษานี้ได้ไหม" ไม่ได้ถามเกี่ยวกับขนาดของไวยากรณ์หรือเกี่ยวกับว่าน้ำตาลในไวยากรณ์บางส่วนจะทำให้มันเล็กลง Combinatorial Explosion ที่คุณพูดถึงหมายความว่าการจัดการองค์ประกอบจำนวนมากโดยไม่มีการเปลี่ยนแปลง 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 อธิบายทุกอย่างได้ดี
บอ

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>

ซึ่งดูเหมือนจะตรงกับคำถามของคุณ


minOccursและmaxOccursถูก จำกัด ให้ 1 xs:allสำหรับเด็ก
Pavel Minaev

Pavel: ขอบคุณ ... ฉันพบสิ่งนี้หลังจากตรวจสอบโพสต์ของฉันอีกครั้งแล้วแก้ไขเพื่อลบ xs: all
Steven_W

1

หากวิธีการข้างต้นไม่ได้ผลคุณอาจกำลังดำเนินการกับ EDI trasaction ซึ่งคุณต้องตรวจสอบผลลัพธ์ของคุณกับสคีมา HIPPA หรือ xsd ที่ซับซ้อนอื่น ๆ สำหรับเรื่องนั้น ข้อกำหนดคือกล่าวว่ามี 8 กลุ่ม REF และส่วนใดส่วนหนึ่งจะต้องปรากฏในลำดับใดก็ได้และไม่จำเป็นต้องมีทั้งหมดหมายความว่าคุณอาจมีตามลำดับที่ 1 REF, REF ที่ 3, REF ที่ 2, REF ที่ 9 ภายใต้สถานการณ์เริ่มต้นที่ได้รับ 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>

สารละลาย:

เพียงแค่แทนที่ "ลำดับ" ด้วย "ทั้งหมด" หรือใช้ "ตัวเลือก" ด้วยชุดค่าผสมขั้นต่ำ / สูงสุดจะไม่ได้ผล!

สิ่งแรกแทนที่"xs:sequence" with "<xs:all>" ตอนนี้คุณต้องทำการเปลี่ยนแปลงบางอย่างที่คุณกำลังอ้างถึงองค์ประกอบจากที่นั่นไปที่:

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

*** ตอนนี้ในส่วนด้านบนให้เพิ่มจุดทริกเกอร์ในส่วนท้ายเช่น trigger_field นี้ = "REF01 _... ชื่อเต็ม .. " trigger_value = "38" ทำเช่นเดียวกันกับส่วน REF อื่น ๆ ที่ค่าทริกเกอร์จะแตกต่างกันเช่นพูด "18 "," XX "," YY "เป็นต้นเพื่อให้ข้อมูลบันทึกของคุณมีลักษณะดังนี้:b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">


สิ่งนี้จะทำให้แต่ละองค์ประกอบไม่ซ้ำกันเหตุผลที่เป็นส่วนของ REF ทั้งหมด (ตัวอย่างด้านบน) มีโครงสร้างเหมือนกันเช่น REF01, REF02, REF03 และในระหว่างการตรวจสอบความถูกต้องการตรวจสอบความถูกต้องของโครงสร้างก็ใช้ได้ แต่จะไม่ปล่อยให้ค่าซ้ำกันเนื่องจากพยายามค้นหาค่าที่เหลืออยู่ใน REF แรกเอง การเพิ่มทริกเกอร์จะทำให้พวกเขาไม่ซ้ำกันทั้งหมดและจะส่งผ่านตามลำดับและกรณีสถานการณ์ (เช่นใช้ 5 ใน 9 ไม่ใช่ทั้งหมด 9/9)

หวังว่ามันจะช่วยคุณได้เพราะฉันใช้เวลาเกือบ 20 ชั่วโมงกับเรื่องนี้

โชคดี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.