2008-10-18 8 views
43

मेरे पास एक साधारण वर्ग है जो अनिवार्य रूप से केवल कुछ मान रखता है। मैंने एक अच्छा स्ट्रिंग प्रस्तुति वापस करने के लिए ToString() विधि को ओवरराइड कर दिया है।XmlDode के बिना Cml में XmlNode/XmlElement बनाना?

अब, मैं एक ToXml() विधि बनाना चाहते हैं, जो कुछ इस तरह वापस आ जाएगी:

<Song> 
    <Artist>Bla</Artist> 
    <Title>Foo</Title> 
</Song> 

बेशक, मैं सिर्फ एक StringBuilder यहाँ इस्तेमाल कर सकते हैं, लेकिन मैं वापस जाने के लिए चाहते हैं एक XmlNode या XmlElement, XmlDocument.AppendChild के साथ उपयोग किया जाना है।

मैं XmlDocument.CreateElement बुला से एक XmlElement अन्य बनाने के लिए सक्षम होने के लिए नहीं है, तो मुझे आश्चर्य है कि अगर मैं कुछ भी अनदेखा कर दिया, या मैं वास्तव में या तो या तो एक XmlDocument या ref XmlElement के साथ काम करने में पारित करने के लिए है, या है फ़ंक्शन एक स्ट्रिंग लौटाता है जिसमें एक्सएमएल मैं चाहता हूं?

+0

सवाल शीर्षक सामग्री/उद्देश्य सवाल के अनुरूप नहीं है। आप जानना चाहते हैं कि अपनी कक्षाओं को क्रमबद्ध कैसे करें। मुझे xerviceNode के उदाहरण को webservice पैरामीटर के रूप में पास करने की आवश्यकता है। उपयोगकर्ता इनपुट स्ट्रिंग से XmlNode बना देगा। –

+1

@DaviFiamenghi - आपकी टिप्पणी सही नहीं है। यदि कोई व्यक्ति XmlNode का उपयोग करके मैन्युअल रूप से एक्सएमएल डेटा बनाने का चयन कर रहा है, जो उनकी पसंद है, तो ऐसे एक्सएमएलएनओड ऑब्जेक्ट्स को .NET में बनाने के लिए ऐसा नहीं लगता है। इसे XmlDocument से बनाये बिना। – antiduh

उत्तर

13

आप कर सकते हैं यह देखना चाहते हैं कि आप प्रत्येक वर्ग पर ToXML() विधि बनाने के बजाय, केवल एक डेटा स्थानांतरण ऑब्जेक्ट बनाने के बजाय XML में किसी ऑब्जेक्ट को क्रमबद्ध और deserialize करने के लिए .NET की अंतर्निहित विशेषताओं का उपयोग कैसे कर सकते हैं।

मैंने इन तकनीकों का सफलतापूर्वक दो परियोजनाओं पर उपयोग किया है लेकिन कार्यान्वयन विवरण अभी आसान नहीं हैं। मैं कुछ समय बाद अपने उत्तरों के साथ अपना जवाब अपडेट करने का प्रयास करूंगा।

यहाँ कुछ उदाहरणों की है कि गूगल लौटे है: वेंकट सुब्रमण्यम द्वारा .NET में

एक्सएमएल क्रमबद्धता http://www.agiledeveloper.com/articles/XMLSerialization.pdf

को क्रमानुसार और एक्सएमएल http://www.dotnetfunda.com/articles/article98.aspx

में एक वस्तु deserialize कैसे अपने .NET ऑब्जेक्ट एक्सएमएल अनुकूलित .NET एक्सएमएल गुणों के साथ क्रमबद्धता http://blogs.microsoft.co.il/blogs/rotemb/archive/2008/07/27/customize-your-net-object-xml-serialization-with-net-xml-attributes.aspx

2

आपको सटीक होने के लिए लिंक - System.Xml.Linq की आवश्यकता है।

आप स्क्रैच से XElement का उपयोग कर एक्सएमएल बना सकते हैं - कि काफी तरह तुम बाहर करना चाहिए।

15

W3C से Document Object Model (Core) Level 1 विनिर्देश (बोल्ड मेरा है):

एपीआई इस विनिर्देश द्वारा परिभाषित के अधिकांश इंटरफ़ेस हैं बल्कि वर्गों की तुलना में । इसका मतलब है कि वास्तविक कार्यान्वयन को परिभाषित नामों और निर्दिष्ट ऑपरेशन के साथ केवल विधियों का खुलासा करने की आवश्यकता है, वास्तव में उन वर्गों को लागू करें जो सीधे इंटरफेस से मेल खाते हैं। यह की अनुमति देता है डोम एपीआई अलग वर्ग पदानुक्रम के साथ अपने स्वयं के डेटा संरचनाओं, या नए अनुप्रयोगों के शीर्ष पर साथ अनुप्रयोगों विरासत के शीर्ष पर एक पतली पोशिश के रूप में लागू किया जाना। यह भी मतलब है कि साधारण कंस्ट्रक्टर्स (जावा में या सी ++ भावना), डोम वस्तुओं बनाने के लिए इस्तेमाल नहीं किया जा सकता क्योंकि अंतर्निहित वस्तुओं डोम इंटरफेस को थोड़ा रिश्ता हो सकता का निर्माण किया जाना है। वस्तु उन्मुख डिजाइन में पारंपरिक समाधान यह करने के लिए कारखाना तरीकों कि वस्तुओं कि विभिन्न इंटरफेस को लागू की उदाहरण बना परिभाषित करने के लिए है। डोम में स्तर 1, कुछ इंटरफेस "X" एक द्वारा बनाई गई हैं "createX()" विधि दस्तावेज़ इंटरफेस पर लागू करने की वस्तुओं; इस वजह से सभी डोम वस्तुओं एक विशिष्ट दस्तावेज़ के संदर्भ में रहते हैं।

AFAIK, आप किसी भी XmlNode (XmlElement, XmlAttribute, XmlCDataSection, आदि) XmlDocument एक निर्माता से छोड़कर नहीं बना सकते।

इसके अलावा, ध्यान दें कि आप नोड्स ही दस्तावेज़ के कारखाने विधियों के माध्यम से नहीं बनाई गई हैं के लिए XmlDocument.AppendChild() उपयोग नहीं कर सकते। मामले में आप दूसरे दस्तावेज से एक नोड है, तो आप XmlDocument.ImportNode() उपयोग करना चाहिए।

40

मैं XmlDocument सामग्री के बजाय System.Xml.Linq के XDoc और XElement का उपयोग करने की अनुशंसा करता हूं। यह बेहतर होगा और आप क्वेरी करने और अपने XML पार्स करने में LINQ शक्ति का उपयोग करने में सक्षम हो जाएगा:

XElement का उपयोग करना, अपने ToXml() विधि निम्नलिखित तरह दिखेगा:

public XElement ToXml() 
{ 
    XElement element = new XElement("Song", 
         new XElement("Artist", "bla"), 
         new XElement("Title", "Foo")); 

    return element; 
} 
1

आप XmlElement या XmlNode वापस नहीं कर सकते हैं, क्योंकि वे वस्तुएं हमेशा और केवल XmlDocument के संदर्भ में मौजूद होती हैं।

एक्सएमएल सीरियलाइजेशन XElement लौटने से थोड़ा आसान है, क्योंकि आपको केवल इतना करना है कि गुणों के साथ गुण गुण हैं और सीरिएलाइज़र आपके लिए सभी एक्सएमएल पीढ़ी करता है। (इसके अलावा आपको नि: शुल्क निराशा मिलती है, मान लीजिए कि आपके पास पैरामीटर रहित कन्स्ट्रक्टर है और, अच्छी तरह से, अन्य चीजों का एक समूह है।)

दूसरी ओर, ए) आपको इसे करने के लिए XmlSerializer बनाना है, बी) से निपटना संग्रह गुण काफी नो-ब्रेनर नहीं है जिसे आप इसे पसंद कर सकते हैं, और सी) एक्सएमएल क्रमबद्धता बहुत गूंगा है; यदि आप जेनरेट कर रहे हैं तो आप भाग्य से कुछ भी करना चाहते हैं तो आप भाग्य से बाहर हैं।

कई मामलों में, उन मुद्दों से कोई फर्क नहीं पड़ता। मैं एक के लिए एक विधि लिखने के बजाय गुणों के साथ मेरी गुणों को चिह्नित करना होगा।

4

आप अपने वर्ग में ToXML विधि के लिए एक XmlDocument लौट सकता है, तो जब आप बस की तरह कुछ का उपयोग परिणाम दस्तावेज़ के साथ तत्व जोड़ने के लिए जा रहे हैं: "Desired_Element_Name के लिए

XmlDocument returnedDocument = Your_Class.ToXML(); 

XmlDocument finalDocument = new XmlDocument(); 
XmlElement createdElement = finalDocument.CreateElement("Desired_Element_Name"); 
createdElement.InnerXML = docResult.InnerXML; 
finalDocument.AppendChild(createdElement); 

इस तरह पूरे मूल्य "आपके परिणाम पर XmlDocument लौटा दस्तावेज़ की पूरी सामग्री होगी।

मुझे उम्मीद है कि इससे मदद मिलती है।

XmlNode existing_node; // of some document, where we don't know necessarily know the XmlDocument... 
XmlDocument temp = new XmlDocument(); 
temp.LoadXml("<new><elements/></new>"); 
XmlNode new_node = existing_node.OwnerDocument.ImportNode(temp.DocumentElement, true); 
existing_node.AppendChild(new_node); 

गुड लक:

4

सामग्री आप चाहते हैं के साथ एक नया XmlDocument बनाएं और फिर अपने मौजूदा दस्तावेज़ में आयात करें, अपने मौजूदा नोड्स के OwnerDocument संपत्ति एक्सेस करके।

2

एक और विकल्प एक प्रतिनिधि को विधि में पास करना है, जो एक्सएमएलएलमेंट बनाएगा। इस तरह लक्ष्य विधि को पूरे XmlDocument तक पहुंच नहीं मिलेगी, लेकिन नए तत्व बनाने में सक्षम होंगे।

-2
XmlDocumnt xdoc = new XmlDocument; 
XmlNode songNode = xdoc.CreateNode(XmlNodeType.Element, "Song", schema) 
xdoc.AppendChild..... 
8

एक्सएमएलएनओड्स एक मालिक दस्तावेज़ संपत्ति के साथ आते हैं।

शायद तुम सिर्फ कर सकते हैं:

//Node is an XmlNode pulled from an XmlDocument 
XmlElement e = node.OwnerDocument.CreateElement("MyNewElement"); 
e.InnerText = "Some value"; 
node.AppendChild(e); 
2

सिर्फ एक subclassed XmlDocument के रूप में अपने डेटा वर्ग (ते) बनाने क्यों विचार नहीं है, तो आप मुक्त करने के लिए यह सब मिलता है। आपको किसी भी ऑफ-डॉक नोड्स को क्रमबद्ध करने या बनाने की आवश्यकता नहीं है, और आपको वह संरचना मिलती है जो आप चाहते हैं।

यदि आप इसे अधिक परिष्कृत बनाना चाहते हैं, तो बेस क्लास लिखें जो XmlDocument का उप-वर्ग है, फिर इसे मूल एक्सेसर्स दें, और आप सेट हैं।

यहाँ एक सामान्य प्रकार मैं एक परियोजना के लिए एक साथ रखा है ...

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Xml; 
using System.IO; 

namespace FWFWLib { 
    public abstract class ContainerDoc : XmlDocument { 

     protected XmlElement root = null; 
     protected const string XPATH_BASE = "/$DATA_TYPE$"; 
     protected const string XPATH_SINGLE_FIELD = "/$DATA_TYPE$/$FIELD_NAME$"; 

     protected const string DOC_DATE_FORMAT = "yyyyMMdd"; 
     protected const string DOC_TIME_FORMAT = "HHmmssfff"; 
     protected const string DOC_DATE_TIME_FORMAT = DOC_DATE_FORMAT + DOC_TIME_FORMAT; 

     protected readonly string datatypeName = "containerDoc"; 
     protected readonly string execid = System.Guid.NewGuid().ToString().Replace("-", ""); 

     #region startup and teardown 
     public ContainerDoc(string execid, string datatypeName) { 
      root = this.DocumentElement; 
      this.datatypeName = datatypeName; 
      this.execid = execid; 
      if(null == datatypeName || "" == datatypeName.Trim()) { 
       throw new InvalidDataException("Data type name can not be blank"); 
      } 
      Init(); 
     } 

     public ContainerDoc(string datatypeName) { 
      root = this.DocumentElement; 
      this.datatypeName = datatypeName; 
      if(null == datatypeName || "" == datatypeName.Trim()) { 
       throw new InvalidDataException("Data type name can not be blank"); 
      } 
      Init(); 
     } 

     private ContainerDoc() { /*...*/ } 

     protected virtual void Init() { 
      string basexpath = XPATH_BASE.Replace("$DATA_TYPE$", datatypeName); 
      root = (XmlElement)this.SelectSingleNode(basexpath); 
      if(null == root) { 
       root = this.CreateElement(datatypeName); 
       this.AppendChild(root); 
      } 
      SetFieldValue("createdate", DateTime.Now.ToString(DOC_DATE_FORMAT)); 
      SetFieldValue("createtime", DateTime.Now.ToString(DOC_TIME_FORMAT)); 
     } 
     #endregion 

     #region setting/getting data fields 
     public virtual void SetFieldValue(string fieldname, object val) { 
      if(null == fieldname || "" == fieldname.Trim()) { 
       return; 
      } 
      fieldname = fieldname.Replace(" ", "_").ToLower(); 
      string xpath = XPATH_SINGLE_FIELD.Replace("$FIELD_NAME$", fieldname).Replace("$DATA_TYPE$", datatypeName); 
      XmlNode node = this.SelectSingleNode(xpath); 
      if(null != node) { 
       if(null != val) { 
        node.InnerText = val.ToString(); 
       } 
      } else { 
       node = this.CreateElement(fieldname); 
       if(null != val) { 
        node.InnerText = val.ToString(); 
       } 
       root.AppendChild(node); 
      } 
     } 

     public virtual string FieldValue(string fieldname) { 
      if(null == fieldname) { 
       fieldname = ""; 
      } 
      fieldname = fieldname.ToLower().Trim(); 
      string rtn = ""; 
      XmlNode node = this.SelectSingleNode(XPATH_SINGLE_FIELD.Replace("$FIELD_NAME$", fieldname).Replace("$DATA_TYPE$", datatypeName)); 
      if(null != node) { 
       rtn = node.InnerText; 
      } 
      return rtn.Trim(); 
     } 

     public virtual string ToXml() { 
      return this.OuterXml; 
     } 

     public override string ToString() { 
      return ToXml(); 
     } 
     #endregion 

     #region io 
     public void WriteTo(string filename) { 
      TextWriter tw = new StreamWriter(filename); 
      tw.WriteLine(this.OuterXml); 
      tw.Close(); 
      tw.Dispose(); 
     } 

     public void WriteTo(Stream strm) { 
      TextWriter tw = new StreamWriter(strm); 
      tw.WriteLine(this.OuterXml); 
      tw.Close(); 
      tw.Dispose(); 
     } 

     public void WriteTo(TextWriter writer) { 
      writer.WriteLine(this.OuterXml); 
     } 
     #endregion 

    } 
} 
संबंधित मुद्दे