#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();
}
}
}