Невозможно проанализировать и прочитать XML-данные

#c# #xml #linq #xml-parsing

#c# #xml #linq #xml-синтаксический анализ

Вопрос:

У меня есть формат xml, как показано ниже. И пытается прочитать элементы из содержимого, названия продукта и идентификатора продукта, но не может. Вот что я пробовал до сих пор, но безуспешно. Оба моих подхода не работают, любая помощь приветствуется.

 <source xml:base="https://google.com/api/v1" xmlns="http://www.w3.org/2005/Atom" > 
  <id>s1</id>  
  <value>
    <id>value1</id>
    <version>1.90</version>
        <content type="application/xml">
            <x:products>
                <n:Productname>3M</n:Productname>
                <n:ProductId n:type="Int32">97</n:ProductId>       
            </x:products>
            <x:products>
                <n:Productname>HD</n:Productname>
                <n:ProductId n:type="Int32">99</n:ProductId>       
            </x:products>
        </content>
  </value>
</source>

 FileStream fs = new FileStream(xmlFile, FileMode.Open, FileAccess.Read);
            XmlDocument xmldoc = new XmlDocument();           
            XmlNodeList xmlnodecontent;

            xmldoc.Load(fs);           

            xmlnodecontent = xmldoc.GetElementsByTagName("content");
            for (int i = 0; i < xmlnodecontent.Count; i  )
            {
                var innerXml =xmlnodecontent[i].ChildNodes.Item(0).InnerXml;
                //Trying to read product here
            }

 //Second approach

      var doc = XDocument.Load(xmlFile);

      var units = from u in doc.Descendants("value")
                        select new
                        {
                            Id = (int)u.Element("id"),
                            content = from entry in doc.Descendants("content")
                                      select new
                                      {
                                          product = (int)u.Element("d:Product"),
                                      }
                        };
            foreach (var unit in units)
            {
                var id = unit.Id;
                var content = unit.content;
            }
 

Комментарии:

1. Отправленный xml содержит префиксы пространства имен (например, x:, n:). Все эти пространства имен должны быть объявлены, написав, например, xmlns:x=»некоторый URI» и т.д. В противном случае xml недействителен и не может быть проанализирован (поэтому XDocument.Load(xmlFile); будет выдано исключение).

2. К сожалению, у меня нет контроля над XML-данными, которые я получаю. Есть ли способ обойти это.

3. В вашем XML нет объявления xml ( <?xml etc ?> ), это просто фрагмент. Добавьте некоторый текст в файл, который включает объявление и некоторые элементы с объявленными пространствами имен, а затем добавьте соответствующие закрывающие теги элемента

4. Эта часть также не является допустимым xml <n:Productname>3M</d:Product> , из-за этого ее очень сложно анализировать, даже если URI пространств имен, где есть

Ответ №1:

Я исправил XML-файл и использовал xml linq (XDocument) для получения значений

 <source xml:base="https://google.com/api/v1" xmlns="http://www.w3.org/2005/Atom" xmlns:x="abc" xmlns:n="def" >
  <id>s1</id>
  <value>
    <id>value1</id>
    <version>1.90</version>
    <content type="application/xml">
      <x:products>
        <n:Productname>3M</n:Productname>
        <n:ProductId n:type="Int32">97</n:ProductId>
      </x:products>
      <x:products>
        <n:Productname>HD</n:Productname>
        <n:ProductId n:type="Int32">99</n:ProductId>
      </x:products>
    </content>
  </value>
</source>
 

Вот этот код :

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:temptest.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            XElement value = doc.Descendants().Where(x => x.Name.LocalName == "value").FirstOrDefault();
            XNamespace ns = value.GetDefaultNamespace();
            XNamespace xNs = value.GetNamespaceOfPrefix("x");
            XNamespace nNs = value.GetNamespaceOfPrefix("n");

            var values = doc.Descendants(ns   "value").Select(x => new
            {
                id = (string)x.Element(ns   "id"),
                products = x.Descendants(xNs   "products").Select(y => new
                {
                    name = (string)y.Element(nNs   "Productname"),
                    id = (string)y.Element(nNs   "ProductId")
                }).ToList()
            }).ToList();
        }
    }
}