【问题标题】:how to take desired value from the multiple same elements in the xml by using LInq c#如何使用 LInq c# 从 xml 中的多个相同元素中获取所需的值
【发布时间】:2017-10-02 15:23:57
【问题描述】:

我正在解析一个包含 <es:qrxlev> 节点的 XML 文件。有时这些节点直接在<xn:attributes> 节点中找到,有时在更深的位置找到它们,例如在<es:pciConflictCell><es:pciDictictCell> 节点中。

我直接在<xn:attributes>节点中追<es:qrxlev>节点的值。

我的 XML 是

<?xml version="1.0" encoding="utf-8" ?>
<xn:VsDataContainer id=test">
  <xn:attributes>
    <xn:vsDataType>vsDataEUtranCellFDD</xn:vsDataType>
    <es:crsGain>0</es:crsGain>
    <es:pciConflictCell>
      <es:enbId>66111</es:enbId>
      <es:qrxlev>3</es:qrxlev>
    </es:pciConflictCell>
    <es:pciConflictCell>
      <es:enbId>66111</es:enbId>
      <es:qrxlev>7</es:qrxlev>
    </es:pciConflictCell>
    <es:pciDictictCell>
      <es:enbId>66111</es:enbId>
      <es:qrxlev>8</es:qrxlev>
    </es:pciDictictCell>
    <es:pdcchLaGinrMargin>100</es:pdcchLaGinrMargin>
    <es:lbEUtranAcceptOffloadThreshold>50</es:lbEUtranAcceptOffloadThreshold>
    <es:pdcchCfiMode>5</es:pdcchCfiMode>
    <es:qrxlev>10</es:qrxlev>
    <es:zzzTemporary21>-2000000000</es:zzzTemporary21>
  </xn:attributes>
</xn:VsDataContainer>

我现在使用的代码是:

List<XElement> vsDataEUtranCellFDD = vsDataContainers.Where(x => x.Descendants().Where(a => (a.Name.LocalName == "vsDataType") && ((string)a == "vsDataEUtranCellFDD")).Any()).ToList();

     List<CellName> cells = vsDataEUtranCellFDD.Select(x => new CellName()
                                                {
    if (vsDataEUtranCellFDD.Any()) 
    {
        List<CellName> cells = vsDataEUtranCellFDD
            .Select(x => new CellName() 
            {
                qrxlev= (int)x.Descendants()
                    .Where(a => a.Name.LocalName == "qrxlev")
                    .FirstOrDefault()
            };
    }

此代码的问题在于它返回 all &lt;es:qrxlev&gt; 节点值,而不仅仅是属性节点中的值。我怎样才能只获得我想要的特定值而不是所有值?

【问题讨论】:

    标签: c# xml linq


    【解决方案1】:

    不要使用Descendants(),它会获取树中的所有节点。使用Elements(),获取当前节点的直接子节点

    var xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
        <xn:VsDataContainer id=""test"" xmlns:xn=""xn"" xmlns:es=""es"">
          <xn:attributes>
            <xn:vsDataType>vsDataEUtranCellFDD</xn:vsDataType>
            <es:crsGain>0</es:crsGain>
            <es:pciConflictCell>
              <es:enbId>66111</es:enbId>
              <es:qrxlev>3</es:qrxlev>
            </es:pciConflictCell>
            <es:pciConflictCell>
              <es:enbId>66111</es:enbId>
              <es:qrxlev>7</es:qrxlev>
            </es:pciConflictCell>
            <es:pciDictictCell>
              <es:enbId>66111</es:enbId>
              <es:qrxlev>8</es:qrxlev>
            </es:pciDictictCell>
            <es:pdcchLaGinrMargin>100</es:pdcchLaGinrMargin>
            <es:lbEUtranAcceptOffloadThreshold>50</es:lbEUtranAcceptOffloadThreshold>
            <es:pdcchCfiMode>5</es:pdcchCfiMode>
            <es:qrxlev>10</es:qrxlev>
            <es:zzzTemporary21>-2000000000</es:zzzTemporary21>
          </xn:attributes>
        </xn:VsDataContainer>";
    
    XNamespace xnNamespace = "xn";
    XNamespace esNamespace = "es";
    
    var xmlElement = XElement.Parse(xml);
    var qrxlev = xmlElement
        .Element(xnNamespace + "attributes")
        .Element(esNamespace + "qrxlev")
        .Value;
    

    这将返回10,即第四个&lt;es:qrxlev&gt; 元素的值。

    我不得不对您的 xml 进行一些修改:

    • 您没有声明任何命名空间
    • 您的 test 属性引用不正确

    【讨论】:

    • 这是一个巨大的文件,我将所需的部分分配给 c# 类,然后使用它。这对类有用吗???
    • 也许吧?我得看看你的课才知道。但是,如果您正在使用 XElement 进行 xml 解析,看起来您就是这样,那么它应该就可以了。去试试吧。
    • 如果我使用 qrxlev= (int)x.Element(un+"cellId")
    • 使用现有代码有什么办法可以找到直接子值
    【解决方案2】:

    如果您想要最高级别的定义,请创建一个方法来查找树中节点的级别,如下所示:

    static int GetDocLevel(XElement e) {
        var res = 0;
        while (e != null) {
            res++;
            e = e.Parent;
        }
        return res;
    }
    

    现在你可以按级别排序,取最前面的:

    XNamespace esNs = "http://www.es.org"; // <<== The actual namespace goes here
    var topQrxlev = doc.Descendants(esNs + "qrxlev").OrderBy(GetDocLevel).FirstOrDefault();
    

    这是一个运行示例:

    class Program {
        static int GetDocLevel(XElement e) {
            var res = 0;
            while (e != null) {
                res++;
                e = e.Parent;
            }
            return res;
        }
    
        static void Main(string[] args) {
            var xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
    <xn:VsDataContainer
        xmlns:es=""http://www.es.org""
        xmlns:xn=""http://www.xn.org""
    >
    <xn:attributes>
      <xn:vsDataType>vsDataEUtranCellFDD</xn:vsDataType>
      <es:crsGain>0</es:crsGain>
      <es:pciConflictCell>
        <es:enbId>66111</es:enbId>
        <es:qrxlev>3</es:qrxlev>
      </es:pciConflictCell>
      <es:pciConflictCell>
        <es:enbId>66111</es:enbId>
        <es:qrxlev>7</es:qrxlev>
      </es:pciConflictCell>
      <es:pciDictictCell>
        <es:enbId>66111</es:enbId>
        <es:qrxlev>8</es:qrxlev>
      </es:pciDictictCell>
      <es:pdcchLaGinrMargin>100</es:pdcchLaGinrMargin>
      <es:lbEUtranAcceptOffloadThreshold>50</es:lbEUtranAcceptOffloadThreshold>
      <es:pdcchCfiMode>5</es:pdcchCfiMode>
      <es:qrxlev>10</es:qrxlev>
      <es:zzzTemporary21>-2000000000</es:zzzTemporary21>
    </xn:attributes>
    </xn:VsDataContainer>";
            var doc = XDocument.Parse(xml);
            XNamespace esNs = "http://www.es.org";
            var topQrxlev = doc.Descendants(esNs + "qrxlev").OrderBy(GetDocLevel).FirstOrDefault();
            Console.WriteLine(topQrxlev?.Value); // Prints 10
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      相关资源
      最近更新 更多