সি # তে এক্সএমএল রিডার সহ এক্সএমএল পড়া


98

আমি নীচের এক্সএমএল ডকুমেন্টটি যত তাড়াতাড়ি পড়তে চেষ্টা করছি এবং অতিরিক্ত ক্লাসে প্রতিটি সাব ব্লকের পাঠ পরিচালনা করতে দিচ্ছি।

<ApplicationPool>
    <Accounts>
        <Account>
            <NameOfKin></NameOfKin>
            <StatementsAvailable>
                <Statement></Statement>
            </StatementsAvailable>
        </Account>
    </Accounts>
</ApplicationPool>

যাইহোক, আমি প্রতিটি অ্যাকাউন্ট এবং পরবর্তীকালে "স্টেটমেন্টস্যাভলভেট" পড়ার জন্য এক্সএমএলআরডার অবজেক্টটি ব্যবহার করার চেষ্টা করছি। আপনি কি XMLReader.Read ব্যবহার করার পরামর্শ দিয়েছেন এবং প্রতিটি উপাদানটি পরীক্ষা করে এটি পরিচালনা করছেন?

আমি প্রতিটি নোডকে সঠিকভাবে পরিচালনা করতে আমার ক্লাসগুলি আলাদা করার কথা ভেবেছি। সুতরাং একটি অ্যাকাউন্টবেস ক্লাস রয়েছে যা একটি এক্সএমএলআরডার উদাহরণ গ্রহণ করে যা নেমআওফকিন এবং অ্যাকাউন্ট সম্পর্কিত আরও কয়েকটি সম্পত্তি পড়বে। তারপরে আমি বিবৃতিগুলির মাধ্যমে ইন্টারঅ্যাক্ট করতে চাইছিলাম এবং অন্য শ্রেণিটি বিবৃতিটি সম্পর্কে নিজেকে পূরণ করুক (এবং পরবর্তীকালে এটি একটি আইলিস্টে যুক্ত কর)।

এখন পর্যন্ত আমার কাছে এক্সপিএমআরইডার তৈরি হয়েছে "প্রতি ক্লাস" অংশটি e ।

সহজ শোনাচ্ছে!


4
সম্পাদনা সহায়তা পেতে সম্পাদনা বাক্সের উপরের ডানদিকে কোণে কমলা প্রশ্ন চিহ্ন ক্লিক করুন। সম্ভবত আপনি একটি কোড ব্লক তৈরি করতে চান যা প্রথমে একটি ফাঁকা রেখা দ্বারা করা হয় এবং তারপরে প্রতিটি লাইন চারটি স্পেস দিয়ে ইন্ডেন্ট করে।
আন্ডারস আবেল

অথবা কেবল আপনার কোড / এক্সএমএল লাইনগুলি নির্বাচন করুন এবং তারপরে সম্পাদক সরঞ্জামদণ্ডে "কোড" বোতামে (101 010) ক্লিক করুন - এত সহজ!
marc_s

উত্তর:


164

আমার অভিজ্ঞতা XmlReaderহ'ল দুর্ঘটনাক্রমে খুব বেশি পড়া খুব সহজ। আমি জানি আপনি বলেছেন যে আপনি এটি যত তাড়াতাড়ি পড়তে চান, তবে আপনি কি এর পরিবর্তে কোনও ডিওএম মডেল ব্যবহার করার চেষ্টা করেছেন ? আমি খুঁজে পেয়েছি যে লিনকিউ থেকে এক্সএমএল এক্সএমএলকে কাজ অনেক সহজ করে তোলে ।

যদি আপনার দস্তাবেজটি বিশেষত বিশাল হয় তবে আপনি আপনার প্রতিটি "বাহ্যিক" উপাদানগুলির জন্য একটি স্ট্রিমিং পদ্ধতিতে XmlReaderএকটি XElementথেকে তৈরি করে এক্সএমএলে লিনকিউ সংযুক্ত করতে পারেন XmlReader: এটি আপনাকে লিনিকুতে এক্সএমএল রূপান্তরকরণের বেশিরভাগ কাজ করতে দেয় তবে এখনও কেবল প্রয়োজন স্মৃতিতে দস্তাবেজের একটি ছোট অংশ যেকোন এক সময়। এখানে কিছু নমুনা কোড রয়েছে ( এই ব্লগ পোস্ট থেকে কিছুটা অভিযোজিত ):

static IEnumerable<XElement> SimpleStreamAxis(string inputUrl,
                                              string elementName)
{
  using (XmlReader reader = XmlReader.Create(inputUrl))
  {
    reader.MoveToContent();
    while (reader.Read())
    {
      if (reader.NodeType == XmlNodeType.Element)
      {
        if (reader.Name == elementName)
        {
          XElement el = XNode.ReadFrom(reader) as XElement;
          if (el != null)
          {
            yield return el;
          }
        }
      }
    }
  }
}

আমি স্ট্যাকওভারফ্লো ব্যবহারকারীর ডেটা (যা প্রচুর) এর আগে অন্য ফর্ম্যাটে রূপান্তর করতে এটি ব্যবহার করেছি - এটি খুব ভালভাবে কাজ করে।

রাডারবাব থেকে সম্পাদনা করুন, জন পুনরায় ফর্ম্যাট করেছেন - যদিও এটি "স্পষ্টভাবে খুব বেশি পড়ুন" সমস্যাটি উল্লেখ করা হচ্ছে তা পুরোপুরি পরিষ্কার নয় ...

এটি বাসা বাঁধাকে সহজ করে এবং "একটি খুব বেশি পঠনযোগ্য" সমস্যার যত্ন নেওয়া উচিত।

using (XmlReader reader = XmlReader.Create(inputUrl))
{
    reader.ReadStartElement("theRootElement");

    while (reader.Name == "TheNodeIWant")
    {
        XElement el = (XElement) XNode.ReadFrom(reader);
    }

    reader.ReadEndElement();
}

এটি "খুব বেশি পঠনযোগ্য" সমস্যার যত্ন নেয় কারণ এটি লুপ প্যাটার্নটির সময় ক্লাসিক প্রয়োগ করে:

initial read;
(while "we're not at the end") {
    do stuff;
    read;
}

17
XNode.ReadFrom কল করে উপাদানটি পড়ে এবং পরবর্তীটিতে যায়, তারপরে নীচের পাঠক R পড়ুন () পরেরটি আবার পড়েন। আপনি যদি কোনও উপাদান অবিচ্ছিন্নভাবে মিস করেন তবে তাদের যদি একই নাম হয় এবং ক্রমাগত হয়।
পিবিজেড

4
@ পিবিজেড: ধন্যবাদ আমি নিশ্চিত না যে আমি এটিকে সঠিকভাবে সম্পাদনা করতে বিশ্বাস করি (এটি XMLReader কে আমি কতটা অপছন্দ করি :) আপনি কি এটি সঠিকভাবে সম্পাদনা করতে পারবেন?
জন স্কিটি

4
@ জোনস্কিট - আমি হয়ত কিছু মিস করছি তবে পিবিজেড দ্বারা নির্দেশিত সমস্যাটি সমাধান if(reader.Name == elementName)করার while(reader.Name == elementName)জন্য কেবল পরিবর্তন হবে না?
ডেভিড ম্যাকলিয়ান

4
@pbz: আমি লাইনটি পরিবর্তন করেছি: এক্সেলিমেন্ট এল = এক্সনোড X রিডফ্রোম (রিডার) কে এক্সলেট হিসাবে; হতে হবে: এক্সলেমেন্ট এল = এক্সিলিটি.ল্ড (রিডার.আরডসুব্রি ()); যেহেতু এগুলি এড়িয়ে যাওয়া ধারাবাহিক উপাদানগুলির বাগটি ঠিক করে।
ডিলান হগ

4
অন্যান্য মন্তব্যে যেমন উল্লেখ করা হয়েছে, SimpleStreamAxis()এক্সএমএল ইন্ডেন্টড না থাকাকালীন বর্তমান সংস্করণ উপাদানগুলি এড়িয়ে যাবে কারণ উপাদানটি লোড হওয়ার পরেNode.ReadFrom() পরবর্তী নোডে পাঠককে অবস্থান দেয় - যা পরের শর্তহীন দ্বারা এড়িয়ে যাবে । পরের নোডটি যদি সাদা জায়গা হয় তবে সব ঠিক আছে। অন্যথায়, না। এই সমস্যাটি ছাড়া সংস্করণগুলির জন্য এখানে , এখানে বা এখানে দেখুনRead()
dbc

29

তিন বছর পরে, সম্ভবত ওয়েবএপি এবং এক্সএমএল ডেটার উপর নতুন করে জোর দিয়ে, আমি এই প্রশ্নটি জুড়ে এসেছি। কোডওয়ালা যেহেতু আমি স্ক্যাসিটকে কোনও প্যারাসুট ছাড়াই বিমান থেকে বেরিয়ে যেতে আগ্রহী এবং তার প্রাথমিক কোডটি দ্বিগুণভাবে এমএস এক্সএমএল টিমের নিবন্ধের দ্বারা সংশ্লেষ করার পাশাপাশি বড় এক্সএমএল ডক্সের বিওএল স্ট্রিমিং ট্রান্সফর্মের একটি উদাহরণ দেখে আমি খুব তাড়াতাড়ি অন্যান্য মন্তব্যগুলি উপেক্ষা করেছি , বিশেষত 'পিবিজেড' থেকে, যিনি উল্লেখ করেছেন যে আপনার যদি পর পর নাম অনুসারে একই উপাদান থাকে তবে ডাবল রিডের কারণে অন্য প্রত্যেকে বাদ দেওয়া হয়। এবং প্রকৃতপক্ষে, বিওএল এবং এমএস ব্লগ আর্টিকেলগুলি উভয়ই এই স্তরের প্রভাবটি ছাপিয়ে লক্ষ্যমাত্রার সাথে দ্বিতীয় স্তরের চেয়ে আরও গভীর নীচে নেওয়ার উত্সের নথিগুলি পার্স করছে।

অন্যান্য উত্তরগুলি এই সমস্যার সমাধান করে। আমি কেবলমাত্র একটি সামান্য সরল সংশোধন অফার করতে চেয়েছিলাম যা এখন পর্যন্ত ভালভাবে কাজ করে বলে মনে হয়েছে এবং এটি বিবেচনায় নিয়েছে যে এক্সএমএল বিভিন্ন উত্স থেকে আগত হতে পারে, কেবল একটি ইউরি নয়, এবং এক্সটেনশানটি ব্যবহারকারী এক্সএমএলরেডার দ্বারা পরিচালিত এক্সএমএলরেডারটিতে কাজ করে। একটি ধারনা হ'ল পাঠক তার প্রাথমিক অবস্থায় রয়েছে, কারণ অন্যথায় প্রথম 'পড়ুন') একটি পছন্দসই নোড পেরিয়ে যেতে পারে:

public static IEnumerable<XElement> ElementsNamed(this XmlReader reader, string elementName)
{
    reader.MoveToContent(); // will not advance reader if already on a content node; if successful, ReadState is Interactive
    reader.Read();          // this is needed, even with MoveToContent and ReadState.Interactive
    while(!reader.EOF && reader.ReadState == ReadState.Interactive)
    {
        // corrected for bug noted by Wes below...
        if(reader.NodeType == XmlNodeType.Element && reader.Name.Equals(elementName))
        {
             // this advances the reader...so it's either XNode.ReadFrom() or reader.Read(), but not both
             var matchedElement = XNode.ReadFrom(reader) as XElement;
             if(matchedElement != null)
                 yield return matchedElement;
        }
        else
            reader.Read();
    }
}

4
আপনার "যদি (পাঠক.নাম.একওয়ালস (এলিটনাম))" বিবৃতিতে একটি "অন্য পাঠক অনুপস্থিত রয়েছে। পড়ুন ();" বিবৃতি। উপাদানটি যদি আপনি না চান তবে আপনি পড়া চালিয়ে যেতে চান। এটি আমার জন্য কাজ করার জন্য আমাকে যুক্ত করতে হয়েছিল।
ওয়েস

4
@ ওয়েস দুটি কন্ডিশনাল (নোডটাইপ এবং নাম) ভেঙে দিয়ে সমস্যাটি সমাধান করে যাতে else Read()উভয়ের জন্য প্রযোজ্য। এটি ধরার জন্য ধন্যবাদ
mdisibio

4
আমি আপনাকে উত্সাহিত করেছি, তবে দুবার লিখিত পঠন পদ্ধতি কল দেখে আমি খুব খুশি নই। আপনি এখানে লুপ করার সময় একটি ব্যবহার করতে পারেন? :)
নওফাল

অন্য উত্তর যে লক্ষ্য এবং MSDN ডক্সের সঙ্গে একই সমস্যা সমাধান হয়েছে: stackoverflow.com/a/18282052/3744182
DBC

17

আমরা এই জাতীয় এক্সএমএল সর্বদা পার্সিং করি। কীটি সংজ্ঞা দিচ্ছে যেখানে পার্সিং পদ্ধতিটি পাঠককে প্রস্থান করার সময় ছেড়ে যাবে। আপনি যদি সর্বদা পাঠ্য উপাদানটি অনুসরণ করে পরবর্তী উপাদানটিতে পাঠককে সবসময় ছেড়ে যান তবে আপনি নিরাপদে এবং অনুমানযোগ্যভাবে এক্সএমএল স্ট্রিমে পড়তে পারেন। সুতরাং পাঠক যদি বর্তমানে <Account>উপাদানটি সূচক করে থাকেন তবে পাঠককে বিশ্লেষণের পরে </Accounts>সমাপনী ট্যাগকে সূচি দেওয়া হবে ।

পার্সিং কোডটি এরকম কিছু দেখায়:

public class Account
{
    string _accountId;
    string _nameOfKin;
    Statements _statmentsAvailable;

    public void ReadFromXml( XmlReader reader )
    {
        reader.MoveToContent();

        // Read node attributes
        _accountId = reader.GetAttribute( "accountId" );
        ...

        if( reader.IsEmptyElement ) { reader.Read(); return; }

        reader.Read();
        while( ! reader.EOF )
        {
            if( reader.IsStartElement() )
            {
                switch( reader.Name )
                {
                    // Read element for a property of this class
                    case "NameOfKin":
                        _nameOfKin = reader.ReadElementContentAsString();
                        break;

                    // Starting sub-list
                case "StatementsAvailable":
                    _statementsAvailable = new Statements();
                    _statementsAvailable.Read( reader );
                    break;

                    default:
                        reader.Skip();
                }
            }
            else
            {
                reader.Read();
                break;
            }
        }       
    }
}

Statementsশ্রেণী শুধু সার্চ <StatementsAvailable>নোড

public class Statements
{
    List<Statement> _statements = new List<Statement>();

    public void ReadFromXml( XmlReader reader )
    {
        reader.MoveToContent();
        if( reader.IsEmptyElement ) { reader.Read(); return; }

        reader.Read();
        while( ! reader.EOF )
        {
            if( reader.IsStartElement() )
            {
                if( reader.Name == "Statement" )
                {
                    var statement = new Statement();
                    statement.ReadFromXml( reader );
                    _statements.Add( statement );               
                }
                else
                {
                    reader.Skip();
                }
            }
            else
            {
                reader.Read();
                break;
            }
        }
    }
}

Statementবর্গ খুব একই দেখাবে

public class Statement
{
    string _satementId;

    public void ReadFromXml( XmlReader reader )
    {
        reader.MoveToContent();

        // Read noe attributes
        _statementId = reader.GetAttribute( "statementId" );
        ...

        if( reader.IsEmptyElement ) { reader.Read(); return; }

        reader.Read();
        while( ! reader.EOF )
        {           
            ....same basic loop
        }       
    }
}

7

উপ-অবজেক্টগুলির জন্য, ReadSubtree()আপনাকে সাব-অবজেক্টগুলির মধ্যে সীমাবদ্ধ একটি এক্সএমএল-রিডার দেয় তবে আমি সত্যিই মনে করি আপনি এটি কঠোর উপায়ে করছেন। অস্বাভাবিক / অপ্রত্যাশিত এক্সএমএল পরিচালনার জন্য আপনার খুব নির্দিষ্ট প্রয়োজনীয়তা না থাকলে ব্যবহার করুন XmlSerializer(সম্ভবত sgen.exeআপনি যদি চান তবে মিলিত )।

XmlReaderহয় ... জঘন্য বিপরীতে:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
public class ApplicationPool {
    private readonly List<Account> accounts = new List<Account>();
    public List<Account> Accounts {get{return accounts;}}
}
public class Account {
    public string NameOfKin {get;set;}
    private readonly List<Statement> statements = new List<Statement>();
    public List<Statement> StatementsAvailable {get{return statements;}}
}
public class Statement {}
static class Program {
    static void Main() {
        XmlSerializer ser = new XmlSerializer(typeof(ApplicationPool));
        ser.Serialize(Console.Out, new ApplicationPool {
            Accounts = { new Account { NameOfKin = "Fred",
                StatementsAvailable = { new Statement {}, new Statement {}}}}
        });
    }
}

4

নিম্নলিখিত নোডটি বর্তমান নোডের প্রকারটি নির্ধারণ করতে স্ট্রিমের মাধ্যমে নেভিগেট করে এবং তারপরে এক্সএমএল রাইটার সামগ্রীটি এক্সএমএলআরডার সামগ্রী আউটপুট করতে ব্যবহার করে।

    StringBuilder output = new StringBuilder();

    String xmlString =
            @"<?xml version='1.0'?>
            <!-- This is a sample XML document -->
            <Items>
              <Item>test with a child element <more/> stuff</Item>
            </Items>";
    // Create an XmlReader
    using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
    {
        XmlWriterSettings ws = new XmlWriterSettings();
        ws.Indent = true;
        using (XmlWriter writer = XmlWriter.Create(output, ws))
        {

            // Parse the file and display each of the nodes.
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        writer.WriteStartElement(reader.Name);
                        break;
                    case XmlNodeType.Text:
                        writer.WriteString(reader.Value);
                        break;
                    case XmlNodeType.XmlDeclaration:
                    case XmlNodeType.ProcessingInstruction:
                        writer.WriteProcessingInstruction(reader.Name, reader.Value);
                        break;
                    case XmlNodeType.Comment:
                        writer.WriteComment(reader.Value);
                        break;
                    case XmlNodeType.EndElement:
                        writer.WriteFullEndElement();
                        break;
                }
            }

        }
    }
    OutputTextBlock.Text = output.ToString();

নীচের উদাহরণটি উপাদান এবং বৈশিষ্ট্যগুলির বিষয়বস্তু পড়তে XMLReader পদ্ধতি ব্যবহার করে।

StringBuilder output = new StringBuilder();

String xmlString =
    @"<bookstore>
        <book genre='autobiography' publicationdate='1981-03-22' ISBN='1-861003-11-0'>
            <title>The Autobiography of Benjamin Franklin</title>
            <author>
                <first-name>Benjamin</first-name>
                <last-name>Franklin</last-name>
            </author>
            <price>8.99</price>
        </book>
    </bookstore>";

// Create an XmlReader
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
    reader.ReadToFollowing("book");
    reader.MoveToFirstAttribute();
    string genre = reader.Value;
    output.AppendLine("The genre value: " + genre);

    reader.ReadToFollowing("title");
    output.AppendLine("Content of the title element: " + reader.ReadElementContentAsString());
}

OutputTextBlock.Text = output.ToString();

0
    XmlDataDocument xmldoc = new XmlDataDocument();
    XmlNodeList xmlnode ;
    int i = 0;
    string str = null;
    FileStream fs = new FileStream("product.xml", FileMode.Open, FileAccess.Read);
    xmldoc.Load(fs);
    xmlnode = xmldoc.GetElementsByTagName("Product");

আপনি এক্সএমএমএনডের মাধ্যমে লুপ করতে পারেন এবং ডেটা পেতে পারেন ...... সি # এক্সএমএল রিডার


4
এই শ্রেণি অবচিত করা হয়। ব্যবহার করবেন না.
নওফাল

@ এলভারিজম আপনার ভাগ করা ওয়েবসাইটটিতে আরও অনেকগুলি পড়ার এক্সএমএল উপায় রয়েছে এবং এটি আমাকে অনেক সহায়তা করে। আমি আপনাকে ভোট দেবো। XMLReader সহজেই বোঝার জন্য এখানে উদাহরণটি ।
瑲 瑲

0

আমি অনুভব করি না। তবে আমি মনে করি XMLReader অপ্রয়োজনীয়। এটি ব্যবহার করা খুব কঠিন।
এক্সলেট ব্যবহার করা খুব সহজ।
আপনার যদি পারফরম্যান্সের প্রয়োজন হয় (দ্রুত) আপনার অবশ্যই ফাইলের ফর্ম্যাটটি পরিবর্তন করতে হবে এবং স্ট্রিমরিডার এবং স্ট্রিমরাইটার ক্লাসগুলি ব্যবহার করতে হবে।

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