【问题标题】:XmlReader Value don't go through my If-Statement but it shouldXmlReader 值不会通过我的 If 语句,但它应该
【发布时间】:2020-01-12 15:07:56
【问题描述】:

我编写了一个 .graphml 解析器,有一次我需要从特定标签中读取属性值。 Graphml 文件如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:java="http://www.yworks.com/xml/yfiles-common/1.0/java" xmlns:sys="http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
  <!--Created by yEd 3.19.1-->
  <key for="port" id="d0" yfiles.type="portgraphics"/>
  <key for="port" id="d1" yfiles.type="portgeometry"/>
  <key for="port" id="d2" yfiles.type="portuserdata"/>
  <key attr.name="url" attr.type="string" for="node" id="d3"/>
  <key attr.name="description" attr.type="string" for="node" id="d4"/>
  <key for="node" id="d5" yfiles.type="nodegraphics"/>
  <key for="graphml" id="d6" yfiles.type="resources"/>
  <key attr.name="url" attr.type="string" for="edge" id="d7"/>
  <key attr.name="description" attr.type="string" for="edge" id="d8"/>
  <key for="edge" id="d9" yfiles.type="edgegraphics"/>
  <graph edgedefault="directed" id="G">
    <node id="n0">
      <data key="d5">
        <y:UMLClassNode>
          <y:Geometry height="116.0" width="131.0" x="1301.3333333333333" y="41.0"/>
          <y:Fill color="#FFCC00" transparent="false"/>
          <y:BorderStyle color="#000000" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="18.701171875" horizontalTextPosition="center" iconTextGap="4" modelName="internal" modelPosition="c" textColor="#000000" verticalTextPosition="bottom" visible="true" width="138.7421875" x="-3.87109375" xml:space="preserve" y="3.0">&lt;&lt;interface&gt;&gt;Employee</y:NodeLabel>
          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
            <y:AttributeLabel xml:space="preserve">+name:string
+age:int</y:AttributeLabel>
            <y:MethodLabel xml:space="preserve">getName(value:string):String
getTitle():String
getStaffNo():Number
getRoom():String
getPhone()</y:MethodLabel>
          </y:UML>
        </y:UMLClassNode>
      </data>
    </node>
    <node id="n1">
      <data key="d3" xml:space="preserve"/>
      <data key="d4"/>
      <data key="d5">
        <y:UMLClassNode>
          <y:Geometry height="116.0" width="206.0" x="1422.0" y="197.0"/>
          <y:Fill color="#FFCC00" transparent="false"/>
          <y:BorderStyle color="#000000" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.92626953125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="64.67724609375" x="70.661376953125" xml:space="preserve" y="3.0">Customer<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
            <y:AttributeLabel xml:space="preserve">+name:string</y:AttributeLabel>
            <y:MethodLabel xml:space="preserve">+getOrder():string
+payOrder(order:string):int</y:MethodLabel>
          </y:UML>
        </y:UMLClassNode>
      </data>
    </node>
    <node id="n2">
      <data key="d3" xml:space="preserve"/>
      <data key="d4"/>
      <data key="d5">
        <y:UMLClassNode>
          <y:Geometry height="86.0" width="100.0" x="1086.0" y="197.0"/>
          <y:Fill color="#FFCC00" transparent="false"/>
          <y:BorderStyle color="#000000" type="line" width="1.0"/>
          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.92626953125" horizontalTextPosition="center" iconTextGap="4" modelName="custom" textColor="#000000" verticalTextPosition="bottom" visible="true" width="32.9072265625" x="33.54638671875" xml:space="preserve" y="3.0">User<y:LabelModel><y:SmartNodeLabelModel distance="4.0"/></y:LabelModel><y:ModelParameter><y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/></y:ModelParameter></y:NodeLabel>
          <y:UML clipContent="true" constraint="" hasDetailsColor="false" omitDetails="false" stereotype="" use3DEffect="true">
            <y:AttributeLabel xml:space="preserve">+name:string</y:AttributeLabel>
            <y:MethodLabel xml:space="preserve">getName()</y:MethodLabel>
          </y:UML>
        </y:UMLClassNode>
      </data>
    </node>
  </graph>
  <data key="d6">
    <y:Resources/>
  </data>
</graphml>


我特别需要的标签是&lt;node id="n0"&gt; 现在我需要 id 属性的信息。

所以我在本节的解析器代码如下所示:

public List<string> getNodeAttributeValue(XmlReader reader)
        {
            List<string> id = new List<string>();

            while (reader.Read())
            {
                reader.MoveToAttribute("id");
                while (reader.ReadAttributeValue())
                {
                    if (xmlReader.Value.Contains('n'))
                    {
                        string idElement = xmlReader.Value;
                        id.Add(idElement);
                        return id;
                    }
                }
            }
            return id;
        }

当我编译这个时,id 总是空的。使用断点并通过编译变慢我可以看到reader.Value 是这样的:"n0\"\但是为什么这个值没有通过 if 语句?它包含一个字符'n'

空白是个问题吗?如果是,如何在不创建新设置的情况下将空白设置添加到我的阅读器?只需添加设置并在阅读信息后将其删除。

【问题讨论】:

  • 我无法重现您的问题,if 条件正常
  • 嗯,我的只是跳过它。可能是因为我使用了 XmlTextReader 吗?因为我将 XmlTextReader 对象传递给此方法。你只是 XmlReader.Create(filepath) 吗?
  • 是的,我只使用了XmlReader,因为它已在您的示例中使用。此外,从方法返回列表没有意义,您打破循环并返回单个 id 值,您可以简单地返回 string
  • 你有一个必须包含的命名空间。
  • @jdweng 为什么需要包含它?抱歉,我想弄清楚整个标记是如何工作的^^ 但我总是跳过这些 XNamespace 事情

标签: c# xml if-statement xml-parsing graphml


【解决方案1】:

我会使用 xml linq 并使用 id 作为键创建字典

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

namespace ConsoleApplication1
{
    class Program
    {
        const string filename = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(filename);
            XNamespace ns = doc.Root.GetDefaultNamespace();
            XNamespace yns = doc.Root.GetNamespaceOfPrefix("y");
            List<Key> keys = doc.Descendants(ns + "key").Select(x => new Key()
            {
                _for = (string)x.Attribute("for"),
                attrName = (string)x.Attribute("attr.name"),
                id = (string)x.Attribute("id"),
                fileType = (string)x.Attribute("yfiles.type")
            }).ToList();

            Dictionary<string, Key> dict = keys.GroupBy(x => x.id, y => y)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());

            Dictionary<string, List<string>> dict2 = doc.Descendants(ns + "node")
                .SelectMany(x => x.Elements(ns + "data").Select(y => new { id = (string)x.Attribute("id"), key = (string)y.Attribute("key")}))
                .GroupBy(x => x.key, y => y.id)
                .ToDictionary(x => x.Key, y => y.ToList());

            foreach (KeyValuePair<string, List<string>> node in dict2)
            {
                Key key = dict[node.Key];
                key.nodes = node.Value.ToArray();
            }

        }
    }
    public class Key
    {
        public string _for { get; set; }
        public string attrName { get; set; }
        public string id { get; set; }
        public string fileType { get; set; }
        public string[] nodes { get; set; }
    }
}

【讨论】:

  • 如何只能将字典中Key Object的"Id"传递给方法?我有 getModel(XmlReader reader, string id) 需要 id。
  • 我试过了,效果很好,但是当我有多个 id 元素时呢?
  • 你打算有重复的身份证号码吗?我可以将其设为字典中的列表,但我认为在这种情况下没有意义。
  • 不是每个身份证号码都是独立的。但是有很多像n0,n1,n2这样的ID,对于每个ID,我都需要调用getModel方法。
  • 我添加了一个新的命名空间:XNamespace yns = doc.Root.GetNamespaceOfPrefix("y");您需要像我使用 ns 一样使用 yns。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
相关资源
最近更新 更多