Get the value of a child node from a list of nodes

2019-08-27 21:59发布

I am working on an app that generates Node graphs in a 3D environment using Unity. In order to generate the Nodes, I need to assign them values from a Graphml file.

I dont have much experience with XML, so I'm not sure how anything works. I've done some research and tried many things but I cannot make it work.

This is the problem. I want to access the value of the children of each Node/Edge elements. But I don't know how. This is the code I have. The nodes and edges elements are inside xmlNodeLists.

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using Topology;

public class GraphMLReaderThree : MonoBehaviour {

public TextAsset xmlRawFile;

void Start()
{
    string data = xmlRawFile.text;

    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(data);

    int scale = 2;

    XmlNodeList nodeList = xmlDoc.GetElementsByTagName("node");
    XmlNodeList edgeList = xmlDoc.GetElementsByTagName("edge");
    Debug.Log(nodeList.Count);
    XmlNode targetNode = 
    nodeList[0].SelectNodes("//data[@key='author.activity']")[0];
    if (targetNode != null)
    {
        string valor = targetNode.InnerText;
        Debug.Log(valor);
    }
    else
    {
        Debug.Log("No nodes found");
    }
} 

And this is one node of the Graphml. I dont know how to access those Children with the data key thing.

    <node id="247983">
        <data key="author.regDate">2010-10-27 23:09:40</data>
        <data key="author.location">Raleigh, NC</data>
        <data key="author.descr">The official twitter account for Red Hat 
        Training, Certification, and Consulting</data>
        <data key="author.pub.descr">Twitter</data>
        <data key="author.country">us</data>
        <data key="author.website">http://www.redhat.com/services</data>
        <data key="author.friends">813</data>
        <data key="author.activity">1</data>
        <data key="author.origId">208736299</data>
        <data key="author.personName">Red Hat Services</data>
        <data key="author.pub.id">11</data>
        <data key="author.tzone">Central Time (US &amp; Canada)</data>
        <data key="author.lon">-78.6386</data>
        <data key="author.name">RedHat_Services</data>
        <data key="author.lat">35.7721</data>
        <data key="author.audience">18155</data>
        <data key="author.eigen.centrality">1.0</data>
        <data key="author.modularity.class">247983</data>
        <data key="author.modularity.size">15</data>
        <data key="coords.x">7.624482</data>
        <data key="coords.y">-11.719869</data>
        <data key="coords.z">-0.9229746</data>
    </node>

The problem is, the Debug.Log skips to "No Nodes Found". But the Lists are full of node elements and the xPath query is correct. Maybe im not using the correct functions. I expect to get the value 1 of this child in particular "author.Activity" child in particular. And once it works, get all children and assign them to the 3D Node values.

2条回答
虎瘦雄心在
2楼-- · 2019-08-27 22:23

I used XML Linq to create a nested dictionary :

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

namespace ConsoleApplication100
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            Dictionary<string, Dictionary<string, string>> dict = doc.Descendants("node")
                .GroupBy(x => (string)x.Attribute("id"), y => y.Elements("data")
                    .GroupBy(a => (string)a.Attribute("key"), b => (string)b)
                    .ToDictionary(a => a.Key, b => b.FirstOrDefault()))
                    .ToDictionary(x => x.Key, y => y.FirstOrDefault());

        }
    }
}
查看更多
老娘就宠你
3楼-- · 2019-08-27 22:35

Xpath doesn't give me the results for some reason. It gives me a Null exception. So I tried with another approach and I made it work. It's a dirty solution, since I will need to add 20 more conditions, but at least it gives me the information from the XML selectively.

For now this works for me until I find an optimized solution. Thanks for the help!

void Start () {
    string data = xmlRawFile.text;
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(data);
    XmlNodeList nodes = xmlDoc.GetElementsByTagName("node");
    Debug.Log(nodes.Count);

    foreach (XmlNode node in nodes)
    {
        string aux=node.Attributes["id"].Value;           
        XmlNodeList childs = node.ChildNodes;

        Debug.Log(childs.Count);
        Debug.Log(aux);
        for(int i=0; i<childs.Count;i++)
        {
            if(childs[i].Attributes["key"].Value == "author.name")
            {
                Debug.Log(childs[i].InnerText);
            }            
        }
    }
}
查看更多
登录 后发表回答