কোনও এক্সেলিমেটের ইনারএক্সএমএল পাওয়ার সর্বোত্তম উপায়?


147

bodyনীচের কোডটিতে মিশ্র উপাদানগুলির বিষয়বস্তু পাওয়ার সর্বোত্তম উপায় কী ? উপাদানটিতে এক্সএইচটিএমএল বা পাঠ্য থাকতে পারে, তবে আমি কেবল তার সামগ্রীটি স্ট্রিং আকারে চাই। এই XmlElementধরণের InnerXmlসম্পত্তি রয়েছে যা আমি ঠিক পরে করছি।

লিখিত কোডটি প্রায় যা আমি চাই তা করতে পারে তবে এতে পার্শ্ববর্তী <body>... </body>উপাদান রয়েছে যা আমি চাই না।

XDocument doc = XDocument.Load(new StreamReader(s));
var templates = from t in doc.Descendants("template")
                where t.Attribute("name").Value == templateName
                select new
                {
                   Subject = t.Element("subject").Value,
                   Body = t.Element("body").ToString()
                };

উত্তর:


208

আমি দেখতে চেয়েছিলাম যে এই প্রস্তাবিত সমাধানগুলির মধ্যে কোনটি সর্বোত্তমভাবে সম্পাদিত হয়েছিল, তাই আমি কিছু তুলনামূলক পরীক্ষা চালিয়েছি। আগ্রহের বাইরে, আমি লিনকিউ পদ্ধতিগুলি গ্রেগের প্রস্তাবিত প্লেইন পুরাতন System.XML পদ্ধতির সাথেও তুলনা করি । তারতম্যটি আকর্ষণীয় ছিল এবং আমার প্রত্যাশা মতো নয়, ধীরতম পদ্ধতিগুলি দ্রুততমের চেয়ে 3 গুণ বেশি ধীর হয়

সবচেয়ে দ্রুততম দ্বারা অর্ডার করা ফলাফলগুলি:

  1. ক্রিয়েটরিডার - ইনস্ট্যান্স হান্টার (0.113 সেকেন্ড)
  2. সরল পুরানো সিস্টেম.এক্সএমএল - গ্রেগ হারলম্যান (0.134 সেকেন্ড)
  3. স্ট্রিং কনটেনটেশনের সাথে সমষ্টি - মাইক পাওয়েল (0.324 সেকেন্ড)
  4. স্ট্রিংবিল্ডার - ভিন (০.৩৩৩ সেকেন্ড)
  5. স্ট্রিং.আরনে যোগ দিন - টেরি (0.360 সেকেন্ড)
  6. অ্যারেতে স্ট্রিং.কনকাট - মার্সিন কোসিরাডজকি (0.364)

পদ্ধতি

আমি 20 টি অভিন্ন নোড সহ একটি একক এক্সএমএল নথি ব্যবহার করেছি (যাকে 'ইঙ্গিত' বলা হয়):

<hint>
  <strong>Thinking of using a fake address?</strong>
  <br />
  Please don't. If we can't verify your address we might just
  have to reject your application.
</hint>

উপরের সেকেন্ড হিসাবে প্রদর্শিত সংখ্যাগুলি হ'ল 20 টি নোডের "অভ্যন্তরীণ এক্সএমএল" টানা, একাধারে একাধিক বার এবং 5 রানের গড় (গড়) নেওয়ার ফলাফল। এক্সএমএলটিকে XmlDocument( সিস্টেম.এক্সএমএল পদ্ধতির জন্য) বা XDocument(অন্য সকলের জন্য ) মধ্যে এক্সএমএল লোড করার এবং পার্স করার সময়টি আমি অন্তর্ভুক্ত করিনি ।

আমি যে লিনিকিউ অ্যালগরিদম ব্যবহার করেছি সেগুলি হ'ল: (সি # - সবাই একটি XElement"পিতামাতা" নেয় এবং অভ্যন্তরীণ এক্সএমএল স্ট্রিংটি ফেরত দেয়)

CreateReader:

var reader = parent.CreateReader();
reader.MoveToContent();

return reader.ReadInnerXml();

স্ট্রিং কনটেন্টেশন সহ সমষ্টি:

return parent.Nodes().Aggregate("", (b, node) => b += node.ToString());

StringBuilder:

StringBuilder sb = new StringBuilder();

foreach(var node in parent.Nodes()) {
    sb.Append(node.ToString());
}

return sb.ToString();

স্ট্রিং.আরনে যোগ দিন:

return String.Join("", parent.Nodes().Select(x => x.ToString()).ToArray());

স্ট্রিং.আরকে কনক্যাট:

return String.Concat(parent.Nodes().Select(x => x.ToString()).ToArray());

আমি এখানে "সরল পুরাতন সিস্টেম। এক্সএমএল" অ্যালগরিদম দেখাইনি কারণ এটি কেবল কল করছে।


উপসংহার

যদি পারফরম্যান্স গুরুত্বপূর্ণ হয় (যেমন প্রচুর এক্সএমএল, প্রায়শই পার্স করা হয়) তবে আমি প্রতিবার ড্যানিয়েলের পদ্ধতিটি ব্যবহার করবCreateReader । আপনি যদি কেবল কয়েকটি প্রশ্ন করছেন তবে আপনি মাইকের আরও সংক্ষিপ্ত সমষ্টি পদ্ধতিটি ব্যবহার করতে চাইতে পারেন।

যদি আপনি প্রচুর নোড (সম্ভবত 100 এর) সাথে বড় উপাদানগুলিতে এক্সএমএল ব্যবহার করেন তবে আপনি সম্ভবত StringBuilderসমষ্টি পদ্ধতি ব্যবহার করে সুবিধাটি দেখতে শুরু করেছেন তবে শেষ হয়নি CreateReader। আমি মনে করি না যে একটি বৃহত তালিকাকে একটি বড় অ্যারেতে রূপান্তর করার শাস্তির কারণে (এমনকি ছোট তালিকা সহ এটিও সুস্পষ্ট) কারণগুলি Joinএবং Concatপদ্ধতিগুলি এই পরিস্থিতিতে আরও কার্যকর হবে।


স্ট্রিংবিল্ডার সংস্করণটি একটি লাইনে লেখা যেতে পারে: var ফলাফল = প্যারেন্ট E উপাদানসমূহ () gক্যবদ্ধ (নতুন স্ট্রিংবিল্ডার (), (এসবি, xelem) => এসবি.অপেন্ডলাইন (xelem.ToString ()), sb => sb.ToString ( ))
সফটলিয়ন

7
আপনি মিস করেছেন parent.CreateNavigator().InnerXml( using System.Xml.XPathএক্সটেনশন পদ্ধতির প্রয়োজন)।
রিচার্ড

আপনার মনে হয় নি যে আপনার .ToArray()ভেতরের দরকার আছে .Concat, তবে এটি এটি আরও দ্রুত করে দেবে বলে মনে হচ্ছে
ড্রাগজাস

যদি আপনি এই উত্তরগুলোর নীচের দিকে স্ক্রোল করুন না: শুধু থেকে ধারক / রুট stripping বিবেচনা .ToString()প্রতি এই উত্তর । আরও দ্রুত বলে মনে হচ্ছে ...
ড্রাজস

2
আপনার সত্যই এটি var reader = parent.CreateReader();একটি ব্যবহারের বিবৃতিতে মোড়ানো উচিত ।
BrainSlugs83

70

আমি মনে করি এটি একটি আরও ভাল পদ্ধতি (ভিবিতে, অনুবাদ করা শক্ত হওয়া উচিত নয়):

একটি এক্সলেমেন্ট এক্স দেওয়া হয়েছে:

Dim xReader = x.CreateReader
xReader.MoveToContent
xReader.ReadInnerXml

নিস! প্রস্তাবিত অন্যান্য কয়েকটি পদ্ধতির তুলনায় এটি অনেক দ্রুত (আমি সেগুলি পরীক্ষা করেছিলাম - বিশদটির জন্য আমার উত্তর দেখুন)। যদিও তারা সবাই কাজটি করে, এটি দ্রুততম করে - এমনকি এটি System.XML.Node.InnerXML এর চেয়েও দ্রুত দেখায়!
লুক স্যাম্পসন

4
এক্সএমএল রিডারটি ডিসপোজযোগ্য, তাই এটি ব্যবহার করে মোড়ানো ভুলবেন না দয়া করে (আমি ভিবি জানতাম তবে আমি নিজের উত্তরটি সম্পাদনা করব)।
দিমিত্রি ফেদোরকভ

19

এক্সলেমেন্টে এই "এক্সটেনশন" পদ্ধতিটি ব্যবহার সম্পর্কে কীভাবে? আমার জন্য কাজ!

public static string InnerXml(this XElement element)
{
    StringBuilder innerXml = new StringBuilder();

    foreach (XNode node in element.Nodes())
    {
        // append node's xml string to innerXml
        innerXml.Append(node.ToString());
    }

    return innerXml.ToString();
}

অথবা কিছুটা লিনক ব্যবহার করুন

public static string InnerXml(this XElement element)
{
    StringBuilder innerXml = new StringBuilder();
    doc.Nodes().ToList().ForEach( node => innerXml.Append(node.ToString()));

    return innerXml.ToString();
}

নোট : উপরে কোড ব্যবহার করা হয়েছে element.Nodes()যেমন উল্টোদিকে element.Elements()। দুজনের মধ্যে পার্থক্য মনে রাখা খুব গুরুত্বপূর্ণ বিষয়। element.Nodes()তোমার মত সবকিছু দেয় XText, XAttributeইত্যাদি, কিন্তু XElementশুধুমাত্র একটি উপাদান।


15

যারা সেরা পদ্ধতির সন্ধান করেছেন এবং প্রমাণ করেছেন তাদের সকল allণ দিয়ে (ধন্যবাদ!), এখানে এটি একটি এক্সটেনশন পদ্ধতিতে আবৃত করা হয়েছে:

public static string InnerXml(this XNode node) {
    using (var reader = node.CreateReader()) {
        reader.MoveToContent();
        return reader.ReadInnerXml();
    }
}

10

এটি সহজ এবং দক্ষ রাখুন:

String.Concat(node.Nodes().Select(x => x.ToString()).ToArray())
  • সমষ্টি হ'ল মেমরি এবং কর্মক্ষমতা অকার্যকর যখন স্ট্রিং সংমিশ্রণ
  • জয়েন ("", sth) ব্যবহার করে কনক্যাটের চেয়ে দু'বার বড় স্ট্রিং অ্যারে ব্যবহার করা হচ্ছে ... এবং কোডটিতে বেশ অদ্ভুত দেখাচ্ছে।
  • + = ব্যবহার করা খুব অদ্ভুত দেখাচ্ছে, তবে সম্ভবত '+' ব্যবহারের চেয়ে খুব খারাপ নয় - সম্ভবত একই কোডে অনুকূলিত হবে, কারণ নির্ধারিতকরণের ফলাফলটি অব্যবহৃত এবং সংকলক দ্বারা নিরাপদে অপসারণ করা যেতে পারে।
  • স্ট্রিংবিল্ডার এতটা প্রয়োজনীয়

7

আমি এটি ব্যবহার করে শেষ করেছি:

Body = t.Element("body").Nodes().Aggregate("", (b, node) => b += node.ToString());

এটি প্রচুর স্ট্রিং কনটেনটেশন করবে - আমি নিজেরাই স্ট্রিংবিল্ডারের ব্যবহার ভিনকে পছন্দ করতাম। ম্যানুয়াল foreach একটি নেতিবাচক নয়।
মার্ক গ্র্যাভেল

এই পদ্ধতিটি আমাকে আজ সত্যিই বাঁচিয়েছে, নতুন কন্সট্রাক্টরের সাথে একটি এক্সিলমেন্ট লেখার চেষ্টা করছে এবং অন্য কোনও পদ্ধতির কোনও হাতের মুঠোয়ই হাতের মুঠোয় ছিল না, যখন এইটি করেছে did ধন্যবাদ!
ডেলিওটগ

3

ব্যক্তিগতভাবে, আমি InnerXmlসমষ্টি পদ্ধতি ব্যবহার করে একটি এক্সটেনশন পদ্ধতি লিখে শেষ করেছি :

public static string InnerXml(this XElement thiz)
{
   return thiz.Nodes().Aggregate( string.Empty, ( element, node ) => element += node.ToString() );
}

আমার ক্লায়েন্ট কোডটি তখন পুরানো সিস্টেমের সাথে ঠিক তেমনই সংশ্লেষিত হয় X এক্সএমএল নেমস্পেস:

var innerXml = myXElement.InnerXml();

2

@ গ্রেগ: মনে হচ্ছে আপনি নিজের উত্তরটিকে সম্পূর্ণ আলাদা উত্তর হিসাবে সম্পাদনা করেছেন। আমার উত্তরটি হ্যাঁ, আমি System.XML ব্যবহার করে এটি করতে পারতাম তবে লিনকু থেকে এক্সএমএল দিয়ে আমার পা ভিজে যাওয়ার আশা করছিলাম।

আমি কেবলমাত্র XElement এর ব্যবহার করতে পারি না কেন অন্য কেউ যদি অবাক হয়ে যায় তবে আমি নীচে আমার আসল জবাবটি ছেড়ে দেব I আমার যা প্রয়োজন তা পাওয়ার জন্য সম্পত্তি মূল্য নির্ধারণ করুন:

@ গ্রেগ: মান সম্পত্তি যে কোনও শিশু নোডের সমস্ত পাঠ্য বিষয়বস্তুকে সম্মতি দেয়। সুতরাং যদি শরীরের উপাদানটিতে কেবল পাঠ্য থাকে তবে এটি কাজ করে, তবে এটিতে যদি এক্সএইচটিএমএল থাকে তবে আমি সমস্ত পাঠ একসাথে একত্রিত করি তবে কোনও ট্যাগ নেই।


আমি এই সঠিক একই সমস্যা গাড়ীতে আঘাত এবং এটা একটি বাগ ছিল: আমি 'মিশ্র বিষয়বস্তু (যেমন ছিল <root>random text <sub1>child</sub1> <sub2>child</sub2></root>) যা হয়ে ওঠে random text childchildমাধ্যমেXElement.Parse(...).Value
drzaus

1

// রিজেক্স ব্যবহার করা সহজ এবং শেষ উপাদান ট্যাগটি ছাঁটাই করতে আরও দ্রুত হতে পারে

var content = element.ToString();
var matchBegin = Regex.Match(content, @"<.+?>");
content = content.Substring(matchBegin.Index + matchBegin.Length);          
var matchEnd = Regex.Match(content, @"</.+?>", RegexOptions.RightToLeft);
content = content.Substring(0, matchEnd.Index);

1
ঝরঝরে। কেবলমাত্র ব্যবহারের জন্য আরও দ্রুত IndexOf:var xml = root.ToString(); var begin = xml.IndexOf('>')+1; var end = xml.LastIndexOf('<'); return xml.Substring(begin, end-begin);
ড্রাজস

1

ডক্টর.স্ট্রাস্টিং () বা ডক্ট.টোস্ট্রিং (SaveOptions) কাজ করে। দেখুন http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.tostring(v=vs.110).aspx


না, তা হয় না। এটিতে এর সমস্ত বৈশিষ্ট্যযুক্ত উপাদানও রয়েছে। শুরু এবং শেষ ট্যাগের মধ্যে কেবল সামগ্রীটিই চেয়েছিল।
ক্রিস্টোফ

0

এখানে লিনকিউ ব্যবহার না করে কাজ শুরু করার জন্য কি সিস্টেম.এক্সএমএল নামের স্থানের অবজেক্টগুলি ব্যবহার করা সম্ভব? আপনি ইতিমধ্যে উল্লিখিত হিসাবে, XMLNode.InnerXML আপনার প্রয়োজন হিসাবে ঠিক হয়।


0

ভাবছি কিনা (লক্ষ্য করুন আমি বি + = থেকে মুক্তি পেয়েছি এবং কেবল বি + আছে)

t.Element( "body" ).Nodes()
 .Aggregate( "", ( b, node ) => b + node.ToString() );

তুলনায় কিছুটা কম দক্ষ হতে পারে

string.Join( "", t.Element.Nodes()
                  .Select( n => n.ToString() ).ToArray() );

100% নিশ্চিত নয় ... তবে সমষ্টি () এবং স্ট্রিং-এ জয়েন () রিফ্লেক্টরের দিকে ঝলকানো ... আমার মনে হয় আমি এটিকে সমষ্টি হিসাবে কেবল একটি রিটার্নিং মান সংযোজন হিসাবে পড়েছি, তাই মূলত আপনি পাবেন:

স্ট্রিং = স্ট্রিং + স্ট্রিং

বনাম স্ট্রিং.জাইন, এটি ফাস্টস্ট্রিংএলোকেশন বা অন্য কিছুতে উল্লেখ আছে, যা আমার কাছে মাইক্রোসফ্টের লোকেরা সেখানে কিছু বাড়তি পারফরম্যান্স বাড়িয়ে দিয়েছে। অবশ্যই আমার .ToAraray () আমার এটাকে অস্বীকার করুন, তবে আমি কেবল একটি অন্য প্রস্তাব দিতে চেয়েছিলাম।


0

তুমি জান? সবচেয়ে ভাল কাজটি হল সিডিএটিএ ফিরে আসা :( আমি এখানে সমাধানগুলি দেখছি তবে আমার মনে হয় সিডিএটিএ সবচেয়ে সহজ এবং সস্তার, এটির সাথে বিকাশের পক্ষে সবচেয়ে সুবিধাজনক নয়



-2
public static string InnerXml(this XElement xElement)
{
    //remove start tag
    string innerXml = xElement.ToString().Trim().Replace(string.Format("<{0}>", xElement.Name), "");
    ////remove end tag
    innerXml = innerXml.Trim().Replace(string.Format("</{0}>", xElement.Name), "");
    return innerXml.Trim();
}

এছাড়াও যদি উপাদানটির কোনও বৈশিষ্ট্য থাকে বা কেবলমাত্র একটি স্থান খুব বেশি যুক্তি ব্যর্থ হয়।
ক্রিস্টোফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.