Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / XML / March 2007

Tip: Looking for answers? Try searching our database.

Serializing Class with Unqualified Root Element and Default Namespace attribute

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Mark Olbert - 12 Mar 2007 01:04 GMT
I'm trying to serialize (using XmlSerializer.Serialize) a class that I generated from an XSD schema using XSD.EXE /c.

The problem I'm running into is that the root element needs to be unqualified, and the default namespace needs to be included on it
as an attribute. The schema I'm using is this:

<xs:schema
    xmlns:x="urn:schemas-microsoft-com:office:excel"
    xmlns:html="http://www.w3.org/TR/REC-html40"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:c="urn:schemas-microsoft-com:office:component"
    attributeFormDefault="unqualified"
    targetNamespace="urn:schemas-microsoft-com:office:spreadsheet"
    elementFormDefault="unqualified">
        <xs:import namespace="urn:schemas-microsoft-com:office:office" />
        <xs:import namespace="urn:schemas-microsoft-com:office:excel" />
        <xs:import namespace="urn:schemas-microsoft-com:office:component" />
        <xs:element name="Workbook">...
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="o:DocumentProperties" />
                <xs:element ref="o:OfficeDocumentSettings" />
                <xs:element ref="x:ExcelWorkbook" />

But when I use Serialize() I get this:

<?xml version="1.0" encoding="utf-8"?>
    <ss:Workbook
        xmlns:x="urn:schemas-microsoft-com:office:excel"
        xmlns:c="urn:schemas-microsoft-com:office:component"
        xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">...

Which is close, but not close enough.

I tried specifying the default namespace in the call to Serialize(), but it didn't have any effect, on either the qualification on
the Workspace node or the lack of the xmlns attribute on the node.

- Mark

Specifically, I need this:

<Workbook
    xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:x="urn:schemas-microsoft-com:office:excel"
    xmlns:c="urn:schemas-microsoft-com:office:component"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
Martin Honnen - 12 Mar 2007 13:11 GMT
> But when I use Serialize() I get this:
>
[quoted text clipped - 5 lines]
>
> Which is close, but not close enough.

> Specifically, I need this:
>
[quoted text clipped - 3 lines]
>     xmlns:c="urn:schemas-microsoft-com:office:component"
>     xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">

Semantically there is no difference between the two snippets, it does
not matter in terms of XML and namespaces whether a namespace is used as
the default namespace or with a prefix.

Can you show us the relevant C# or VB.NET class definition of the
objects you serialize? There are attributes that set the namespace and
the Serialize method has a third argument that maps prefixes to
namespace URI so this class

    [XmlRoot(Namespace =
"urn:schemas-microsoft-com:office:spreadsheet", ElementName = "Workbook")]
    public class Foo
    {
        public Foo() { }
    }

with this code

            Foo foo = new Foo();
            XmlSerializer serializer = new XmlSerializer(typeof(Foo));
            serializer.Serialize(Console.Out, foo);

serializes as

<Workbook xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="urn:schemas-microsoft-com:office:spreadsheet" />

while using this code

            XmlSerializerNamespaces namespaces = new
XmlSerializerNamespaces();
            namespaces.Add("ss",
"urn:schemas-microsoft-com:office:spreadsheet");
            serializer.Serialize(Console.Out, foo, namespaces);

it serializes as

<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" />

Signature

    Martin Honnen --- MVP XML
    http://JavaScript.FAQTs.com/

Mark Olbert - 12 Mar 2007 17:06 GMT
Martin,

>Semantically there is no difference between the two snippets, it does not matter in terms of XML and namespaces whether a namespace is used as
>the default namespace or with a prefix.

Unfortunately, it appears to matter a great deal to Microsoft Excel. In testing on both Excel XP and Excel 2007, not having that
xmlns="..." attribute prevents the file from being parsed. Personally, and not knowing much about XML, I think having two attributes
that point at the same namespace (i.e., xmlns="..." and xmlns:ss="<same>") strikes me as weird...but apparently not to the folks who
wrote Excel :).

>Can you show us the relevant C# or VB.NET class definition of the objects you serialize? There are attributes that set the namespace and
>the Serialize method has a third argument that maps prefixes to namespace URI so this class

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:schemas-microsoft-com:office:spreadsheet", IsNullable=false)]
public partial class Workbook
{
}

and

XmlSerializer serializer = new XmlSerializer(typeof(Workbook));

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("x", "urn:schemas-microsoft-com:office:excel");
ns.Add("c", "urn:schemas-microsoft-com:office:component");
ns.Add("html", "http://www.w3.org/TR/REC-html40");
ns.Add("ss", "urn:schemas-microsoft-com:office:spreadsheet");

serializer.Serialize(tw, this, ns);    // this is a Workbook object

generates:

<?xml version="1.0" encoding="utf-8"?>
<ss:Workbook xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:c="urn:schemas-microsoft-com:office:component" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
    <Worksheet ss:Name="Sheet1">

which doesn't work because the default xmlns tag is missing. Not adding the "ss" namespace to namespaces generates:

<?xml version="1.0" encoding="utf-8"?>
<Workbook xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:c="urn:schemas-microsoft-com:office:component" xmlns="urn:schemas-microsoft-com:office:spreadsheet">
    <Worksheet d2p1:Name="Sheet1" xmlns:d2p1="urn:schemas-microsoft-com:office:spreadsheet" xmlns="">

which doesn't work because the Worksheet element redefines the default namespace to "". FYI, the Worksheet class definition is as
follows:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:schemas-microsoft-com:office:spreadsheet")]
public partial class WorkbookWorksheet
{
}

Adding the named tag ElementName="Workbook" to the XmlRootAttribute while not adding the ss namespace to the serializer generates

<?xml version="1.0" encoding="utf-8"?>
<Workbook xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:c="urn:schemas-microsoft-com:office:component" xmlns="urn:schemas-microsoft-com:office:spreadsheet">
    <Worksheet d2p1:Name="Sheet1" xmlns:d2p1="urn:schemas-microsoft-com:office:spreadsheet" xmlns="">

which suppresses the ss: prefix on the Workbook node, but still has the problem of the Worksheet node redefining xmlns.

Adding the Namespace= parameter to the XmlTypeAttribute on WorkbookWorksheet:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")]
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:office:spreadsheet")]
public partial class WorkbookWorksheet
{
}

generates

<?xml version="1.0" encoding="utf-8"?>
<Workbook xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:c="urn:schemas-microsoft-com:office:component" xmlns="urn:schemas-microsoft-com:office:spreadsheet">
    <Worksheet d2p1:Name="Sheet1" xmlns:d2p1="urn:schemas-microsoft-com:office:spreadsheet" xmlns="">

again with the redefinition of the default namespace on the Worksheet node.

The schema where Workbook and Worksheet are defined looks like this (some hopefully unrelated details left out for brevity):

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:c="urn:schemas-microsoft-com:office:component" attributeFormDefault="unqualified"
targetNamespace="urn:schemas-microsoft-com:office:spreadsheet" elementFormDefault="unqualified">
    <xs:import namespace="urn:schemas-microsoft-com:office:office" />
    <xs:import namespace="urn:schemas-microsoft-com:office:excel" />
    <xs:import namespace="urn:schemas-microsoft-com:office:component" />
    <xs:element name="Workbook">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Styles">
                </xs:element>
                <xs:element maxOccurs="unbounded" name="Worksheet">
                    <xs:complexType>
                        <xs:sequence>
                        </xs:sequence>
                        <xs:attribute ref="ss:Name" use="required" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
...

I appreciate your help, and look forward to other suggestions.

- Mark
Martin Honnen - 12 Mar 2007 18:31 GMT
> The schema where Workbook and Worksheet are defined looks like this (some hopefully unrelated details left out for brevity):
>
[quoted text clipped - 3 lines]
> xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:c="urn:schemas-microsoft-com:office:component" attributeFormDefault="unqualified"
> targetNamespace="urn:schemas-microsoft-com:office:spreadsheet" elementFormDefault="unqualified">

Why is elementFormDefault set to unqualified? The MS reference schema
for Office 2003 sets that to qualified.

Signature

    Martin Honnen --- MVP XML
    http://JavaScript.FAQTs.com/

Mark Olbert - 12 Mar 2007 20:42 GMT
Martin,

That schema was generated by having VS2005 generate a schema off of an Excel XP XML file. In the Excel XP XML file the element names
are unqualified (I just double-checked that).

I don't know why that would've changed between Excel XP and Excel 2003.

Interestingly, changing the element form to qualified solved the problem. The generated XML file now looks like:

<?xml version="1.0" encoding="utf-8"?>
<ss:Workbook xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:c="urn:schemas-microsoft-com:office:component" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
 <ss:Worksheet ss:Name="Sheet1">
   <ss:Table>
     <ss:Row ss:Index="1">
       <ss:Cell ss:Index="1">
         <ss:Data ss:Type="String">Ralphie</ss:Data>
       </ss:Cell>
     </ss:Row>
     <ss:Row ss:Index="4">
       <ss:Cell ss:Index="4">
         <ss:Data ss:Type="String">Joanie</ss:Data>
       </ss:Cell>
     </ss:Row>
   </ss:Table>
 </ss:Worksheet>
</ss:Workbook>

which Excel 2007 (I just upgraded, so I no longer have Excel XP to test with) is happy to load as an Excel file.

So the problem's solved (at least for now). Thank you!

I double-checked the file I used to generate the schema to see if it would load in Excel 2007. It does, without a hitch. Here's what
it looks like (edited for brevity):

<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:x="urn:schemas-microsoft-com:office:excel"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:html="http://www.w3.org/TR/REC-html40">
    <Worksheet ss:Name="Sheet1">
        <Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="6" x:FullColumns="1"
            x:FullRows="1" ss:DefaultColumnWidth="60" ss:DefaultRowHeight="15">
            <Row ss:AutoFitHeight="0">
                <Cell><Data ss:Type="Number">1</Data></Cell>
            </Row>
            <Row ss:AutoFitHeight="0">
                <Cell><Data ss:Type="Number">2</Data></Cell>
            </Row>
            <Row ss:AutoFitHeight="0"/>
            <Row ss:AutoFitHeight="0">
                <Cell ss:Index="2"><Data ss:Type="String">a</Data></Cell>
            </Row>
            <Row ss:AutoFitHeight="0"/>
            <Row ss:AutoFitHeight="0">
                <Cell ss:Index="4"><Data ss:Type="String">c</Data></Cell>
            </Row>
         </Table>
    </Worksheet>
</Workbook>

I still wish I understood >>why<< it was solved, though, and why Excel XP generated an XML file with unqualified element names. It
looks like, if the xmlns attribute is specified on the root node you don't need to qualify the element names, but if it isn't, you
have to. Since I haven't been able to find a way to get the xmlns attribute added to the root node when I generate a file, I have to
qualify the element names.

Then again, if I had a dollar for every XML/XSD/namespace issue I didn't understand, I'd be filthy rich.

- Mark

>> The schema where Workbook and Worksheet are defined looks like this (some hopefully unrelated details left out for brevity):
>>
[quoted text clipped - 6 lines]
>Why is elementFormDefault set to unqualified? The MS reference schema
>for Office 2003 sets that to qualified.
Martin Honnen - 13 Mar 2007 13:52 GMT
> I double-checked the file I used to generate the schema to see if it would load in Excel 2007. It does, without a hitch. Here's what
> it looks like (edited for brevity):
[quoted text clipped - 6 lines]
>     xmlns:html="http://www.w3.org/TR/REC-html40">
>     <Worksheet ss:Name="Sheet1">

You misunderstand what elementFormDefault="unqualified" means. In that
sample both elements, the Workbook element, and the Worksheet element,
are in the namespace urn:schemas-microsoft-com:office:spreadsheet and a
schema modelling that needs
  targetNamespace="urn:schemas-microsoft-com:office:spreadsheet"
and
  elementFormDefault="qualified"
. The schema you had with a
targetNamespace="urn:schemas-microsoft-com:office:spreadsheet" but with
elementFormDefault="unqualified" describes a Workbook element in the
targetNamespace where child elements like Worksheet are in no namespace,
hence the xmlns="" you got on that element.

Signature

    Martin Honnen --- MVP XML
    http://JavaScript.FAQTs.com/

WenYuan Wang - 15 Mar 2007 12:49 GMT
Hi Mark,

Additionally, XML namespaces is used to provide a simple method for
qualifying element and attribute names used in XML documents.

For example:
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:o="urn:schemas-microsoft-com:office:office"
    xmlns:x="urn:schemas-microsoft-com:office:excel"
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
    xmlns:html="http://www.w3.org/TR/REC-html40">
    <Worksheet ss:Name="Sheet1">

"urn:schemas-microsoft-com:office:spreadsheet' is the default namespace for
both <Workbook> and <WorkSheet> element.

But if you have many <WorkBook> elements with the different meaning in XML
document, then how do you distinguish these <WorkBook> elements?
Namespace can help you in this scenario.

< Workbook xmlns="namespace1">
..< Worksheet >
.....< Workbook xmlns="namespace2">
........
.....</WorkBook>
..</ Worksheet >
</ Workbook>

You can distinguish the root <Workbook> element by namespace "namespace1"
and node <Workbook\Worksheet\Workbook> by namespace "namespace2".

Hope this will help you understand namespace.

You can get more detailed information by the following document.
http://www.w3.org/TR/REC-xml-names/
[Namespaces in XML 1.0 (Second Edition)]

Have a great day,
Sincerley,
Wen Yuan
WenYuan Wang - 19 Mar 2007 15:47 GMT
Hi Martin,

Just want to check whether you have met any further issue?
Please feel free to update here. I'm glad to assist you.

Have a great day,
Sincerely,
Wen Yuan
WenYuan Wang - 12 Mar 2007 13:27 GMT
Hi Mark

According to your description, what you need is the root element should be
unqualified. If I have misunderstood anything here, please feel free to let
me know.

The XSD schema which you posted in newsgroup is fine.

It seems like you Serialize the WorkBook class conjunction with
XmlSerializerNamespaces.
Public void Serialize (XmlWriter xmlWriter, Object o,
XmlSerializerNamespaces namespaces)
Would you please past some code snippet about how did you serialize the
WorkBook Class?

As far as I know, there are two ways you can use to serialize the root
element as unqualified.
Senaro 1:
Stream writer = new FileStream("Workbook.xml", FileMode.Create);
XmlSerializerNamespaces xsnx = new XmlSerializerNamespaces();
xsnx.Add("", " urn:schemas-microsoft-com:office:spreadsheet");
xsns.Add(...); // other namespaces
XmlSerializer serializer = new XmlSerializer(typeof(Workbook));
serializer.Serialize(writer, objWorkbook, xsnx);

Senaro 2:
Stream writer = new FileStream("Workbook.xml", FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(Workbook));
serializer.Serialize(writer, objWorkbook);
       

Hope this helps.
Sincerely,
Wen Yuan
Mark Olbert - 12 Mar 2007 17:07 GMT
Wen Yuan,

Please see my reply to Martin. I tried your suggestions, but they don't solve the problem.

- Mark

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.