【问题标题】:Cannot access to a specific block of XML file with Linq无法使用 Linq 访问特定的 XML 文件块
【发布时间】:2018-06-18 09:27:55
【问题描述】:

我正在尝试获取一个特定的 XML 块,我正在使用函数加载来获取我的所有 XML 文件,它工作正常。当我调试时,我可以看到所有文件。问题在于我何时尝试获取 xml 的特定值。

我正在使用 LINQ 库的 XElement。因此,这是我的 xml 文件的示例:

-<Mission xmlns:z="http:..." xmlns:i="http:..." xmlns="http:..." z:Id="1">
    +<ActiveBullsEye z:Id="2" i:type="BullsEye">
    -<ActiveFlightPlan z:Id="7" i:type="FlightPlan">
        <AIRTAC z:Id="8"/>
        <Active>false</Active>
       -<Aircraft z:Id="9" i:type="a:Tanker" xmlns:a="http:...">
       -<ACColor xmlns:b="http:...">
             <b:A>255</b:A>
             <b:B>169</b:B>
             <b:G>169</b:G>
             <b:R>169</b:R>
             <b:ScA>1</b:ScA>
             <b:ScB>0.396755248</b:ScB>
             <b:ScG>0.396755248</b:ScG>
             <b:ScR>0.396755248</b:ScR>

我需要访问块 (ACColor),然后执行一个 for 语句来获取所有这些值。但我正在尝试这样的事情,但对我不起作用:

XElement xdocument = XElement.load(filepath) //This works
XElement missionBlock = xdocument.Element("Mission") //(ERROR) This not get Mission tag

foreach( XElement acColor in missionBlock.Elements("ACColor") ) { // (ERROR) Not found ACColor
    ...
}

您能帮我访问 ACColor 节点的所有值吗?

【问题讨论】:

  • Here is some documentation。您需要在查询中使用 xml 命名空间。
  • 我会检查,可能命名空间是问题之一......

标签: c# xml linq parsing xelement


【解决方案1】:
XElement xDocument = XElement.load(filepath);  // This works
var ns = xDocument.GetDefaultNamespace();

      in missionBlock
            .Elements(ns + "ActiveBullsEye")    

例如获取z:Id 的值:

var z = xml.GetNamespaceOfPrefix("z");
var id = (string)xElement.Attribute(z + "Id");

从字符串创建命名空间时不要使用 var:

var ns1 = "http://something";         // ns1 is a string
XNamespace ns2 = "http://something";  // ns2 is a namespace

你真的需要一个命名空间 z 来让z + "Id" 工作。

【讨论】:

  • 谢谢,这个解决方案对我有用。但是如果你能告诉我为什么需要在这句话中包含命名空间可能对我有很大帮助。
  • 因为您的 XML 文件定义了该命名空间。它定义了z:i:和第三个不带前缀的,即默认的ns。稍后它还定义了a:b:。更好地了解 xml 命名空间。
  • 好的,谢谢。然后,如果我需要获取特定命名空间的值(如 z 和 i),我需要像之前使用 GetDefault 所做的那样声明这个命名空间......它可能看起来像这样? var ns = "http:..." 如果我​​想引用 i.
  • 是,除了使用var。写XNameSpace z = "http:...";。有一个重载的转换定义不适用于左侧的var
  • 不,那不是命名空间,而是命名空间z 中的属性Id。我会稍微修改一下。
【解决方案2】:

试试这个:

class Program
{
    static void Main(string[] args)
    {
        var xdocument = XDocument.Load(@"c:\temp\sta01\test.xml");
        var xmlns = "http:...";
        var missionBlock = xdocument.Root;
        foreach (
            var acColor 
            in missionBlock
                .Elements(XName.Get("ActiveBullsEye", xmlns))
                .Elements(XName.Get("ActiveFlightPlan", xmlns))
                .Elements(XName.Get("Aircraft", xmlns))
                .Elements(XName.Get("ACColor", xmlns)))
        {
            var channel = acColor.Element(XName.Get("A", xmlns));
            Console.WriteLine($"A: {channel.Value}");
        }
        Console.ReadLine();
    }
}

它适用于这个文档:

<Mission xmlns:z="http:..." xmlns:i="http:..." xmlns="http:..." z:Id="1">
    <ActiveBullsEye z:Id="2" i:type="BullsEye">
        <ActiveFlightPlan z:Id="7" i:type="FlightPlan">
            <AIRTAC z:Id="8"/>
            <Active>false</Active>
            <Aircraft z:Id="9" i:type="a:Tanker" xmlns:a="http:...">
                <ACColor xmlns:b="http:...">
                    <b:A>255</b:A>
                    <b:B>169</b:B>
                    <b:G>169</b:G>
                    <b:R>169</b:R>
                    <b:ScA>1</b:ScA>
                    <b:ScB>0.396755248</b:ScB>
                    <b:ScG>0.396755248</b:ScG>
                    <b:ScR>0.396755248</b:ScR>
                </ACColor>
            </Aircraft>
        </ActiveFlightPlan>
    </ActiveBullsEye>
</Mission>

【讨论】:

  • xml文件中获取值需要使用namespace吗?
【解决方案3】:

使用如下代码的字典:

            XDocument doc = XDocument.Load(FILENAME);
            XElement color = doc.Descendants().Where(x => x.Name.LocalName == "ACColor").FirstOrDefault();

            Dictionary<string, string> dict = color.Elements().GroupBy(x => x.Name.LocalName, y => (string)y)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

【讨论】:

  • 这个解决方案看起来很专业,但我不知道你为什么使用字典来获取值。可能将来你需要使用这个值,你可以从字典中获取它,而不是在 xml 中实现另一个搜索?
  • 你可以使用 List> 因为你得到两个值。我只是认为,如果您要使用成对列表,不妨将其放入字典中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
相关资源
最近更新 更多