2016-03-21 10 views
0

Ich muss ein XML analysieren, wo der Namespace xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" fehlt, so dass das XML wie folgt aussieht:XML-Namespace fehlt für Parser

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<program> 
    <scriptList> 
    <script type="StartScript"> 
    <isUserScript>false</isUserScript> 
    </script> 
    </scriptList> 
</program> 

aber sollte wie folgt aussehen:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<program xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > 
    <scriptList> 
    <script xsi:type="StartScript"> 
     <isUserScript>false</isUserScript> 
    </script> 
    </scriptList> 
</program> 

Das type-Attribut sorgt für die richtige Unterklasse zB

class StartScript : script 
{...} 

Der Parser wird automatisch von einem handgeschriebenen xsd erzeugt über $> xsd.exe a.xsd/Klassen (.NET). Hier ist die xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
elementFormDefault="qualified" attributeFormDefault="qualified"> 

    <!-- Main element --> 
    <xs:element name="program"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name="scriptList"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="script" type="script" maxOccurs="unbounded"/> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 

    <xs:complexType name="script" /> 

    <xs:complexType name="StartScript"> 
    <xs:complexContent> 
     <xs:extension base="script"> 
     <xs:all> 
      <xs:element name="isUserScript" type="xs:boolean"></xs:element> 
     </xs:all> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

Eine einfache Lösung ist es, eine schnur ersetzen zu laufen („type = \‚‘bis‚xsi: type = \‘“) am Eingang XML, aber das ist ziemlich hässlich. Gibt es eine bessere Lösung?

+0

Wie analysierst du es? Verwenden Sie 'XmlSerializer' oder etwas anderes? Gibt es andere Arten von 'Skript' oder nur' StartScript'? – dbc

+0

Parsen ist einfach in C#: _program = (neuer XmlSerializer (typeof (program))) Deserialize (f) als Programm; Es gibt viele Skripte, StartScript ist nur ein Beispiel – Harald

Antwort

1

Sie können Ihre XML in einen Zwischen LINQ to XMLXDocument, fixieren die Attributnamensraum auf den <script> Elemente laden, dann direkt an Ihre letzte Klasse deserialisiert:

// Load to intermediate XDocument 
XDocument xDoc; 
using (var reader = XmlReader.Create(f)) 
    xDoc = XDocument.Load(reader); 

// Fix namespace of "type" attributes 
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance"; 
foreach (var element in xDoc.Descendants("script")) 
{ 
    var attr = element.Attribute("type"); 
    if (attr == null) 
     continue; 
    var newAttr = new XAttribute(xsi + attr.Name.LocalName, attr.Value); 
    attr.Remove(); 
    element.Add(newAttr); 
} 

// Deserialize directly to final class. 
var program = xDoc.Deserialize<program>(); 

die Erweiterungsmethode verwenden:

public static class XObjectExtensions 
{ 
    public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null) 
    { 
     if (element == null) 
      throw new ArgumentNullException(); 
     using (var reader = element.CreateReader()) 
      return (T)(serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader); 
    } 
}