2009-04-18 1 views
0

У меня есть почтовое приложение. При отправке каждому получателю я пишу в файл XML с именем mail.xml. Я использую следующий код:Обеспокоенный написанием xml

Dim from As String = txtFrom.Text 
Dim txto As String = txtTo.Text 
Dim subj As String = txtSubject.Text 
Dim body As String = txtBody.Text 
Dim settings As New XmlWriterSettings() 
settings.Indent = True 
settings.NewLineOnAttributes = True 
Using writer As XmlWriter = XmlWriter.Create("C:\xmlmailfile.xml", settings) 
    writer.WriteStartDocument() 
    writer.WriteStartElement("EMail") 
    writer.WriteStartElement("From") 
    writer.WriteStartAttribute("From") 
    writer.WriteValue(from) 
    writer.WriteEndAttribute() 
    writer.WriteStartElement("To") 
    writer.WriteStartAttribute("To") 
    writer.WriteValue(txto) 
    writer.WriteEndAttribute() 
    writer.WriteStartElement("Subject") 
    writer.WriteStartAttribute("Subject") 
    writer.WriteValue(subj) 
    writer.WriteEndAttribute() 
    writer.WriteStartElement("Body") 
    writer.WriteStartAttribute("Body") 
    writer.WriteValue(body) 
    writer.WriteEndAttribute() 
    writer.WriteEndElement() 
    writer.WriteEndDocument() 
    writer.Flush() 
End Using 

И выход:

<?xml version="1.0" encoding="utf-8" ?> 
<EMail> 
    <From From="[email protected]"> 
    <To To="[email protected]"> 
    <Subject Subject="Hi"> 
     <Body Body="Hello" /> 
    </Subject> 
    </To> 
    </From> 
</EMail> 

Здесь я не могу добавлять к существующему выходу. Выводится только один раздел «Электронная почта». Я хочу добавить раздел «Электронная почта» для каждого получателя. Однако в приведенном выше коде новые разделы заменяют ранее написанные.

Как это сделать?

+0

Ваш XML-дизайн полностью испорчен! – Cerebrus

ответ

7

Документ XML может содержать только один корневой элемент. Я предлагаю вам иметь корневой элемент Emails с элементами Email под ним. Обратите внимание: вы все равно не сможете добавлять новые элементы в один и тот же файл - вам нужно будет прочитать существующий файл и переписать его. В теории вы могли бы просто переписать последнюю строку (вы всегда знаете, как долго она будет, поэтому вы можете просто искать нужное место), но более надежно читать файл в памяти, добавлять новый элемент Email, а затем снова выпишите весь документ.

Я также думаю, что немного странно иметь элемент Bodyв пределах элемент темы. Я хотел бы предложить структуру, как это:

<?xml version="1.0" encoding="utf-8" ?> 
<Emails> 
    <Email> 
    <From Address="[email protected]"> 
    <Recipient Type="To" Address="[email protected]" /> 
    <Recipient Type="Cc" Address="[email protected]" /> 
    <Subject>Hi</Subject> 
    <Body>Body text</Body> 
    </Email> 
    <Email> 
    <!-- Second email comes here --> 
    </Email> 
</Emails> 
+0

Отличный ответ! (как обычно) – Cerebrus

+0

Можете ли вы показать пример, как прочитать файл в памяти, добавить новый элемент электронной почты и как изменить код, чтобы получить результат. – user42348

+0

@ ramyatk06: У меня нет времени на это, прямо сейчас, особенно не в VB, но я уверен, что вы можете найти множество примеров в Интернете. Я предлагаю вам использовать LINQ to XML (если вы используете .NET 3.5) или DOM API (XmlDocument, XmlElement и т. Д.) В противном случае. XmlWriter эффективен, но сложнее получить право. –

0

В дополнении к реализации предложений Джона о необходимых изменениях в ваш XML, вы также должен цикл по WriteXXX методам XMLWriter в. Начните с элемента электронной почты и цикла для каждого получателя.

0

В ответ на ваш комментарий об изменении его в памяти:

Рассмотрим написание схемы, как это:

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:complexType name="FromType"> 
    <xs:attribute name="Address" type="xs:string"/> 
    </xs:complexType> 
    <xs:simpleType name="RecipientMethod"> 
    <xs:restriction base="xs:string"> 
     <xs:enumeration value="To"/> 
     <xs:enumeration value="Cc"/> 
     <xs:enumeration value="Bcc"/> 
    </xs:restriction> 
    </xs:simpleType> 
    <xs:complexType name="RecipientType"> 
    <xs:attribute name="Type" type="RecipientMethod"/> 
    <xs:attribute name="Address" type="xs:string"/> 
    </xs:complexType> 
    <xs:complexType name="Email"> 
    <xs:sequence> 
     <xs:element name="From" type="FromType" minOccurs="1" maxOccurs="1"/> 
     <xs:element name="Recipient" type="RecipientType" minOccurs="1" maxOccurs="unbounded"/> 
     <xs:element name="Subject" type="xs:string" minOccurs="0" maxOccurs="1"/> 
     <xs:element name="Body" type="xs:string" minOccurs="0" maxOccurs="1"/> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:complexType name="Emails"> 
    <xs:sequence> 
     <xs:element name="Emails" type="Email" minOccurs="1" maxOccurs="unbounded"/> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:element name="Emails" type="Emails"/> 
</xs:schema> 

и запустить xsd.exe схемы компилятора на нем (here)

С классом, который он генерирует, вы только что установили элементы, например:

Emails e= new Emails(); 
e.Email = new Email[2]; 
e.Email[0] = new Email(); 
e.Email[0].From = new FromType(); 
... 

После того, как члены установлены, то сделать это:

FileStream f ... 
XmlSerializer x = new XmlSerializer(e, f); 
x.Serialize(e); 

Кроме того, вы можете десериализации:

Emails ne = x.DeSerialize(); 

Затем измените его, чтобы добавить новый e-mail:

Email newEmail = Email[ne.Email.Length + 1]; 
for(int i = 0; i < ne.Email.Length; i++) 
    newEmail[i] = ne.Email[i]; 
newEmail[ne.Email.Length] = new Email(); 
.... 
ne.Email = newEmail; 

затем сериализации его обратно.

+0

извинения, я использовал синтаксис C# - вы можете запустить xsd.exe для генерации кода VB – paquetp

Смежные вопросы