Link to home
Start Free TrialLog in
Avatar of NetworkArchitek
NetworkArchitek

asked on

Creating a simple schema with grouping elements using VS.NET Schema Designer

Hello, I trying to optimize a program I've already written. I used XML and I manually created the "start" and "end" element tags within my code and now I am moving to doing everything directly through a dataset.

The XML file I created in my program before looked like this, without a schema

<Computer>
     <NetworkInfo>
             <NIC MAC="5565.." IP="..." />
             <NIC MAC="455.." IP="..." />
      </NetworkInfo>
      <Processes>
              <PROC Name="svchost.exe" />
              <PROC Name="blahblah.exe" />
      </Processes>
</Computer

There is a lot more but that is basically it. I would really like to keep the same format but use a schema for this (unless this is not the preferred format anymore). I can't figure out how to have elements that just hold other elements, like collection., my <NetworkInfo> element for instance, it just holds NIC elements.

This was very simple to do just doing manually using loops and case statements but again I'd like to take advantage of XSD's and dataset stuff. Using unique "primary keys" and so forth really isn't an option, because in many cases I need data that seems redundant (once it is in my database I use autoincrementing keys so the DB is normalized but removing pseudo-redundancy within my dataset is not an option (for instance many event log erros will have the same data, but I need them all)

Anyway, this may be very simple but I am just not seeing it. Thanks in advance.
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Is this what you are looking for?

It is not annotated, but it should help you to get started

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="Computer">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="NetworkInfo"/>
        <xs:element ref="Processes"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="NetworkInfo">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="NIC"/>
       </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="NIC">
    <xs:complexType>
        <xs:attributeGroup ref="attlist.NIC"/>
    </xs:complexType>
  </xs:element>
  <xs:attributeGroup name="attlist.NIC">
    <xs:attribute name="MAC"/>
    <xs:attribute name="IP"/>
  </xs:attributeGroup>
  <xs:element name="Processes">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="PROC"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="PROC">
    <xs:complexType>
        <xs:attributeGroup ref="attlist.PROC"/>
    </xs:complexType>
  </xs:element>
  <xs:attributeGroup name="attlist.PROC">
    <xs:attribute name="Name"/>
  </xs:attributeGroup>
</xs:schema>
Avatar of NetworkArchitek
NetworkArchitek

ASKER

Thank you!. That's pretty close to perfect. I entered some test data and got this:

<?xml version="1.0" encoding="utf-8" ?>
<pc xmlns="http://tempuri.org/pc.xsd">
      <NetworkInfo>
            <NIC d3p1:MAC="55" d3p1:IP="127.0.0.1" xmlns:d3p1="http://tempuri.org/pc.xsd"></NIC>
            <NIC d3p1:MAC="255" d3p1:IP="192.168.1.1" xmlns:d3p1="http://tempuri.org/pc.xsd"></NIC>
      </NetworkInfo>
      <Processes>
            <PROC d3p1:Name="svchost.exe" xmlns:d3p1="http://tempuri.org/pc.xsd"></PROC>
            <PROC d3p1:Name="mdm.exe" xmlns:d3p1="http://tempuri.org/pc.xsd"></PROC>
      </Processes>
</pc>

Could you explain what you did? Is is sequences that I need to use? Also how can I get rid of this "d3p1" stuff, sorry I've done XML but stuck closely to the way I knew how to do it. =) But otherwise this perfect.
Hi,

1.
Let me explain what this schema is, in between the lines of the schema
(I only copied unique bits)
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<!-- here I define the element Computer, globally so I can use it as a root -->
  <xs:element name="Computer">
<!-- the element type is complex, meaning it contains elements or attributes or both -->
    <xs:complexType>
<!-- the complex type is a sequence of elements -->
      <xs:sequence>
<!-- firts element in the sequence is NetworkInfo, it  occurs once-->
<!-- with the ref attribute I make a reference to an elsewhere defined global element, NetworkInfo-->
       <xs:element ref="NetworkInfo"/>
<!-- second element in the sequence is Processes, it  occurs once-->
        <xs:element ref="Processes"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
<!-- here I define (globally) the element NetworkInfo -->
  <xs:element name="NetworkInfo">
<!-- the element type is complex, meaning it contains elements or attributes or both -->
    <xs:complexType>
<!-- the complex type is a sequence of elements -->
      <xs:sequence>
<!-- there is only one element in the sequence, but it can occur 0 to unbounded times -->
<!-- with the ref attribute I make a reference to an elsewhere defined global element, NIC-->
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="NIC"/>
       </xs:sequence>
    </xs:complexType>
  </xs:element>
<!-- here I define (globally) the element NIC-->
  <xs:element name="NIC">
<!-- the element type is complex, meaning it contains elements or attributes or both -->
    <xs:complexType>
<!-- the content of the element is not defined, I guess you want it to be empty-->
<!-- the attributes of this element are defined in an elsewhere defined attributeGroup-->
        <xs:attributeGroup ref="attlist.NIC"/>
    </xs:complexType>
  </xs:element>
<!-- here is the definition of the attributeGroup -->
  <xs:attributeGroup name="attlist.NIC">
<!-- here are the attribute definitions, please note definitions are local to the group, hence the use of attribute "name" instead of "ref" -->
<!-- attribute types are not defined, so they are just text -->
    <xs:attribute name="MAC"/>
    <xs:attribute name="IP"/>
  </xs:attributeGroup>
<!-- I removed the definition for Processes -->

2.
How did I do this?
I just hand edited the schema, it is not too complex

3.
How to get rid of the d3p1?
This is a bit weird. Allthough syntactically correct, usually this is not done that way.
What you have here is a little namespace game.
With <pc xmlns="http://tempuri.org/pc.xsd"> you define "http://tempuri.org/pc.xsd" to be the default namespace for the root and its childeren.
This means that anything not prefixed would be qualified with the "pc" namespace.
With <NIC d3p1:MAC="55" d3p1:IP="127.0.0.1" xmlns:d3p1="http://tempuri.org/pc.xsd"></NIC> you bind the same namespace to the prefix d3p1,
that is confusing. If you remove the namespace at all, you have an equivalent XML snippet
<NIC MAC="55" IP="127.0.0.1"></NIC> means exactly the same in the above example
I suggest you just delete this namespace information
I assume you did not create the XML yourself, but that it got generated automatically.
Can you tell me about the generation process?

I hope this helps

Gertone
 
Ah thanks for explaining. I didn't notice that the PROC was generate as <PROC ..></PROC>. I guess that is the same. I just basically copied and pasted your code into Visual Studio's XML schema designer and then it has a way for you to insert data into it like it was a database, thats how it was generated.

This has helped me understand the schema's a lot more. Like I said, before whenever I created XML docs I did it without a schema and made documets that look like the one I posted first. I wonder if you could clarify this. When I generate XML documents from datasets I get the kind of format that seemed incorrect/inefficient but I wonder if this is just the preferred way with XSDs. So again I thought the best way would be to have something like this:


<Computer>
     <NetworkInfo>
             <NIC MAC="5565.." IP="..." />
             <NIC MAC="455.." IP="..." />
      </NetworkInfo>
      <Processes>
              <PROC Name="svchost.exe" />
              <PROC Name="blahblah.exe" />
      </Processes>
</Computer

But the way the DataSets work is to basically do something like this:

<SomeRoot>
             <NIC MAC="5565.." IP="..." />
             <NIC MAC="455.." IP="..." />
               <PROC Name="svchost.exe" />
              <PROC Name="blahblah.exe" />
</SomeRoot>

My thinking was you'd want to have "sections", but it seems like with XSDs that is not really the case. I'm really just trying to choose the best/most efficient way of doing this. I guess you can kind of see the kind of data I'm storing, if you could me a suggestion on the best method I'd appreciate. Thanks for all your help!
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
hm .. That actually answers my question and I think that article will definitely help. You've very, very helpful! =)