C# 命名空间管理器无法使用命名空间解析 XML
C# namespace manager doesn't work parsing a XML with namespace
我正在尝试从 this url 中解析 XML,在下面采样,在 C# 中:
<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time='2020-01-16'>
<Cube currency='USD' rate='1.1169'/>
<Cube currency='JPY' rate='122.80'/>
<Cube currency='BGN' rate='1.9558'/>
</Cube>
</Cube>
</gesmes:Envelope>
这是我用来获取货币的代码:
xml.Load(@"https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
XmlNamespaceManager ns = new XmlNamespaceManager(xml.NameTable);
ns.AddNamespace("gesmes", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
XmlNodeList nodes = xml.DocumentElement.SelectNodes("/gesmes:Envelope/Cube/Cube/Cube", ns);
foreach (XmlNode node in nodes)
{
// some code here
}
然而,nodes
总是 null
。我尝试了很多选项,对我有用的唯一选项是从原始 XML 中删除名称空间。但我想直接解析源代码而不做修改。
需要更正三个问题:
您错误定义了与 gesmes
关联的命名空间。
改变
ns.AddNamespace("gesmes", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
至
ns.AddNamespace("gesmes", "http://www.gesmes.org/xml/2002-08-01");
您的 XPath 没有考虑到 Cube
及其后代在默认命名空间中。
为默认命名空间创建前缀:
ns.AddNamespace("eu", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
使用 #2 中的名称空间前缀更新您的 XPath:
/gesmes:Envelope/eu:Cube/eu:Cube/eu:Cube
^^^ ^^^ ^^^
(Cube
的三次方?)
解决上述问题后,您的代码应该可以正常工作。
Linq XML 总是让我不那么头疼:
var doc = XDocument.Load("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
string ns = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";
var outerCube = doc.Root.Element(XName.Get("Cube", ns));
var timeCube = outerCube.Element(XName.Get("Cube", ns));
Console.WriteLine("Time: " + timeCube.Attribute("time").Value);
foreach (var cube in timeCube.Elements())
{
Console.WriteLine(cube.Attribute("currency").Value + " => " + cube.Attribute("rate"));
}
我上个月刚刚为某人编写了相同的代码。使用字典
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 URL = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(URL);
XNamespace ns = doc.Root.GetDefaultNamespace();
Dictionary<string, decimal> dict = doc.Descendants(ns + "Cube").Where(x => x.Attribute("currency") != null)
.GroupBy(x => (string)x.Attribute("currency"), y => (decimal)y.Attribute("rate"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}
我正在尝试从 this url 中解析 XML,在下面采样,在 C# 中:
<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time='2020-01-16'>
<Cube currency='USD' rate='1.1169'/>
<Cube currency='JPY' rate='122.80'/>
<Cube currency='BGN' rate='1.9558'/>
</Cube>
</Cube>
</gesmes:Envelope>
这是我用来获取货币的代码:
xml.Load(@"https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
XmlNamespaceManager ns = new XmlNamespaceManager(xml.NameTable);
ns.AddNamespace("gesmes", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
XmlNodeList nodes = xml.DocumentElement.SelectNodes("/gesmes:Envelope/Cube/Cube/Cube", ns);
foreach (XmlNode node in nodes)
{
// some code here
}
然而,nodes
总是 null
。我尝试了很多选项,对我有用的唯一选项是从原始 XML 中删除名称空间。但我想直接解析源代码而不做修改。
需要更正三个问题:
您错误定义了与
gesmes
关联的命名空间。改变
ns.AddNamespace("gesmes", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
至
ns.AddNamespace("gesmes", "http://www.gesmes.org/xml/2002-08-01");
您的 XPath 没有考虑到
Cube
及其后代在默认命名空间中。为默认命名空间创建前缀:
ns.AddNamespace("eu", "http://www.ecb.int/vocabulary/2002-08-01/eurofxref");
使用 #2 中的名称空间前缀更新您的 XPath:
/gesmes:Envelope/eu:Cube/eu:Cube/eu:Cube ^^^ ^^^ ^^^
(
Cube
的三次方?)
解决上述问题后,您的代码应该可以正常工作。
Linq XML 总是让我不那么头疼:
var doc = XDocument.Load("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
string ns = "http://www.ecb.int/vocabulary/2002-08-01/eurofxref";
var outerCube = doc.Root.Element(XName.Get("Cube", ns));
var timeCube = outerCube.Element(XName.Get("Cube", ns));
Console.WriteLine("Time: " + timeCube.Attribute("time").Value);
foreach (var cube in timeCube.Elements())
{
Console.WriteLine(cube.Attribute("currency").Value + " => " + cube.Attribute("rate"));
}
我上个月刚刚为某人编写了相同的代码。使用字典
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 URL = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(URL);
XNamespace ns = doc.Root.GetDefaultNamespace();
Dictionary<string, decimal> dict = doc.Descendants(ns + "Cube").Where(x => x.Attribute("currency") != null)
.GroupBy(x => (string)x.Attribute("currency"), y => (decimal)y.Attribute("rate"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}