2010-07-27 5 views
1

Je suis en train de développer un système pour récupérer les pièces jointes XML à partir des emails, via les services Web Exchange, et les entrer dans une base de données, via un objet DAL personnalisé que j'ai créé.Analyse d'un fichier XML -options?

J'ai réussi à extraire la pièce jointe XML et l'avoir préparée en tant que flux ... ils se demandent comment analyser ce flux et remplir un objet DAL.

Je peux créer un XMLTextReader et parcourir chaque élément. Je ne vois aucun problème avec cette autre que je soupçonne qu'il y a une manière beaucoup plus lisse. Le lecteur semble traiter l'étiquette d'ouverture, le contenu de l'étiquette et l'étiquette de fermeture comme des éléments différents (en utilisant reader.NodeType). Je m'attendais à ce que myValue soit considéré comme un élément plutôt que trois. Comme je l'ai dit, je peux contourner ce problème, mais je suis sûr qu'il doit y avoir un meilleur moyen.

Je suis tombé sur l'idée d'utiliser un Serializer XML (complètement nouveau pour moi) mais un coup d'oeil rapide a suggéré que ceux-ci ne peuvent pas gérer ArrayLists et List (j'utilise List). Encore une fois, je suis nouveau à LINQ, mais LINQ-to-XML a également été mentionné, mais les exemples que j'ai vus semblent plutôt complexes - bien que ce soit simplement mon manque de familiarité. Fondamentalement, je ne veux pas d'un système cludged, mais je ne veux pas utiliser une technique compliquée avec une courbe d'apprentissage, juste parce que c'est «cool».

Quelle est la manière la plus simple et la plus efficace de traduire ce XML/Stream dans mes objets DAL?

XML Exemple:

<?xml version="1.0" encoding="UTF-8"?> 
<enquiry> 
    <enquiryno>100001</enquiryno> 
    <companyname>myco</companyname> 
    <typeofbusiness>dunno</typeofbusiness> 
    <companyregno>ABC123</companyregno> 
    <postcode>12345</postcode> 
    <contactemail>[email protected]</contactemail> 
    <firstname>My</firstname> 
    <lastname>Name</lastname> 
    <vehicles> 
     <vehicle> 
      <vehiclereg>54321</vehiclereg> 
      <vehicletype>Car</vehicletype> 
      <vehiclemake>Ford</vehiclemake> 
      <cabtype>n/a</cabtype> 
      <powerbhp>130</powerbhp> 
      <registrationdate>01/01/2003</registrationdate> 
     </vehicle> 
    </vehicles> 
</enquiry> 

Mise à jour 1: J'essaie de désérialiser, basé sur l'exemple de Graham. Je pense J'ai mis en place le DAL pour la sérialisation, y compris en spécifiant [XmlElement("whatever")] pour chaque propriété. Et j'ai essayé de désérialiser en utilisant les éléments suivants:

SalesEnquiry enquiry = null; 
XmlSerializer serializer = new XmlSerializer(typeof(SalesEnquiry)); 
enquiry = (SalesEnquiry)serializer.Deserialize(stream); 

Cependant, je reçois une exception: « There is an error in XML document (2, 2) ». Le InnerException déclare {"<enquiry xmlns=''> was not expected."}

Conclusion (mise à jour): problème

Mon précédent était le fait que l'élément dans le fichier XML (enquête) = le nom de la classe (SalesEnquiry)!. Plutôt qu'un attribut [XmlElement] pour la classe, nous avons besoin d'un attribut [XmlRoot] à la place. Pour être complet, si vous souhaitez qu'une propriété de votre classe soit ignorée pendant la sérialisation, utilisez l'attribut [XmlIgnore].

J'ai réussi à sérialiser mon objet et j'ai réussi à prendre le XML entrant et à le dé-sérialiser dans un objet SalesEnquiry.

Cette approche est beaucoup plus simple que l'analyse manuelle du code XML. OK, il y a eu une courbe d'apprentissage abrupte, mais ça valait le coup.

Merci!

+1

La pièce jointe XML est-elle conforme à un schéma particulier? Est-ce toujours le même schéma? Est-ce que vous "déchiquetez" le XML dans des mises en page de table spécifiques, ou stockez le document entier comme un BLOB? – lesscode

+0

@Wayne: Non, il n'y a pas de schéma formel, et certains éléments sont optionnels et seront manquants plutôt que vierges. Les données sont stockées dans quelques tables dans un DB. – CJM

+0

J'ai mis à jour ma réponse en fonction de votre mise à jour. –

Répondre

6

Si votre code XML utilise un schéma (c'est-à-dire que vous allez toujours savoir quels éléments apparaissent et où ils apparaissent dans l'arborescence), vous pouvez utiliser XmlSerializer pour créer vos objets. Vous avez juste besoin de certains attributs sur vos classes pour indiquer au sérialiseur les éléments XML ou les attributs auxquels ils correspondent.Ensuite, il vous suffit de charger votre fichier XML, de créer un nouveau XmlSerializer avec le type de l'objet .NET que vous voulez créer et d'appeler la méthode Deserialize.

Par exemple, vous avez une classe comme ceci:

[Serializable] 
public class Person 
{ 
    [XmlElement("PersonName")] 
    public string Name { get; set; } 

    [XmlElement("PersonAge")] 
    public int Age { get; set; } 

    [XmlArrayItem("Child")] 
    public List<string> Children { get; set; } 
} 

Et XML entrée comme celui-ci (enregistré dans un fichier pour cet exemple):

<?xml version="1.0"?> 
<Person> 
    <PersonName>Bob</PersonName> 
    <PersonAge>35</PersonAge> 
    <Children> 
    <Child>Chris</Child> 
    <Child>Alice</Child> 
    </Children> 
</Person> 

Ensuite, vous créez une instance Person comme ceci:

Person person = null; 
XmlSerializer serializer = new XmlSerializer(typeof(Person)); 
using (FileStream fs = new FileStream(GetFileName(), FileMode.Open)) 
{ 
    person = (Person)serializer.Deserialize(fs); 
} 

Mise à jour: Selon votre dernière mise à jour, j'imagine que vous devez spécifier un attribut XmlRoot sur la classe qui agit en tant qu'élément racine (c.-à-d. SalesEnquiry), ou le XmlSerializer peut être un peu confus que vous référençant un espace de noms vide dans votre XML (xmlns='' ne semble pas correct).

+0

Une fois que j'aurai ce travail (voir ci-dessus), cela devrait être extrêmement pratique, merci. – CJM

+0

J'ai essayé de spécifier un attribut XmlElement pour la classe, mais cela ne l'a pas permis. J'ai également essayé d'ajouter un espace de nom à l'élément de requête, et la même erreur s'est produite au même point. Je suis perplexe. – CJM

+0

@CJM, désolé, mon erreur: ce n'est pas 'XmlElement' dont vous avez besoin au niveau de la classe, mais' XmlRoot'. J'ai mis à jour ma réponse. –

2

XmlSerializer prend en charge les tableaux & listes ... tant que le type contenu est sérialisable.

1

J'ai trouvé Xsd2Code très utile pour ce genre de chose: http://xsd2code.codeplex.com/

Fondamentalement, tout ce que vous devez faire est d'écrire un fichier XSD (fichier de schéma XML) et spécifiez quelques commutateurs de ligne de commande. Xsd2Code génère automatiquement un fichier de classe C# qui contient toutes les classes et propriétés ainsi que tout ce qui est nécessaire pour gérer la sérialisation. Ce n'est pas une solution parfaite car elle ne prend pas en charge tous les aspects de XSD, mais si vos fichiers XML sont des collections d'éléments et d'attributs relativement simples, cela devrait être un bon raccourci pour vous. Il y a un autre projet similaire sur Codeplex appelé Linq à XSD (http://linqtoxsd.codeplex.com/), qui a été conçu pour appliquer toute la spécification XSD, mais la dernière fois que j'ai vérifié, il n'était plus supporté et pas vraiment prêt pour le prime time. Je pensais que ça valait le coup d'être mentionné, cependant.

+0

Merci Dan - aurait pu être utile plus tôt, mais pour une raison quelconque, j'ai créé le DAL puis lié au XML. Si cette application le fait, elle pourrait raccourcir le processus encore plus loin. D'un autre côté, cela a été un exercice d'apprentissage précieux car c'est ... – CJM