C# XElement 没有多次获取同一个标签的多个值
C# XElement is not getting multiple Values for the same Tag multiple times
我有这个 .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"><<interface>>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>
此代码:
public List<Key> AnalyzeNode(XmlReader reader, string filepath)
{
XDocument doc = XDocument.Load(filepath);
XNamespace ns = doc.Root.GetDefaultNamespace();
List<Key> keys = doc.Descendants(ns + "node").Select(x => new Key()
{
id = (string)x.Attribute("id"),
baseModel = AnalyzeNodeLabel<UML_Base>(reader, (string)x.Attribute("id"))
}).ToList();
return keys;
}
public T AnalyzeNodeLabel<T>(XmlReader reader, string id) where T : UML_Base
{
while (reader.Read())
{
XDocument doc = XDocument.Load(this.filepath);
XNamespace ns = "http://www.yworks.com/xml/graphml";
XElement element = doc.Descendants(ns + "NodeLabel").FirstOrDefault();
string interfaceName = element.Value;
if (interfaceName.Contains("<<interface>>") || interfaceName.Contains("interface") || interfaceName.StartsWith("I") && interfaceName.Substring(0, 1).ToUpper().Equals(interfaceName))
{
UML_Interface interfaceModel = new UML_Interface(interfaceName, id);
return (T)Convert.ChangeType(interfaceModel, typeof(UML_Interface));
}
if (interfaceName != null && !interfaceName.Contains("<<interface>>") || !interfaceName.Contains("interface") || !interfaceName.StartsWith("I") && !interfaceName.Substring(0, 1).ToUpper().Equals(interfaceName))
{
UML_Class classModel = new UML_Class(interfaceName, id);
return (T)Convert.ChangeType(classModel, typeof(UML_Class));
}
}
return null;
}
我的问题是 XElement
只获得一个值,但有 3 个 <y:NodeLabel>
标签具有不同的值。对于值,我指的是文本。但是我的 XElement 对象 (from AnalyzeNodeLabel()
) 只是从第一个 <y:NodeLabel>
标签获取值,我如何添加其他标签?也许作为清单?或在一个循环后更新值?那可能吗?
你明确select节点的第一次出现:FirstOrDefault()
您必须 select 循环中的节点:
foreach (var element in doc.Descendants(ns + "NodeLabel"))
{
...
}
更新:
我不知道你为什么打开 Xml-File 两次或者 XmlReader.
发生了什么
如果您只对节点 "node" 和 "NodeLabel"(可能不止一个)感兴趣,那么这可能会有所帮助:
XNamespace yns = "http://www.yworks.com/xml/graphml";
Dictionary<string, List<string>> keys = new Dictionary<string, List<string>>();
foreach (var node in doc.Descendants(ns + "node"))
{
keys[node.Attribute("id").Value] = new List<string>();
foreach (var nodeLabel in node.Descendants(yns + "NodeLabel"))
{
keys[node.Attribute("id").Value].Add(nodeLabel.Value);
}
}
foreach (var entry in keys)
{
Console.WriteLine($"Key: {entry.Key}");
foreach (var basemodel in entry.Value)
{
Console.WriteLine($"->basemodel: {basemodel}");
}
}
输出为:
关键:n0
->basemodel: << interface >>Employee
关键:n1
->基础模型:客户
关键:n2
->基础模型:用户
我有这个 .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"><<interface>>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>
此代码:
public List<Key> AnalyzeNode(XmlReader reader, string filepath)
{
XDocument doc = XDocument.Load(filepath);
XNamespace ns = doc.Root.GetDefaultNamespace();
List<Key> keys = doc.Descendants(ns + "node").Select(x => new Key()
{
id = (string)x.Attribute("id"),
baseModel = AnalyzeNodeLabel<UML_Base>(reader, (string)x.Attribute("id"))
}).ToList();
return keys;
}
public T AnalyzeNodeLabel<T>(XmlReader reader, string id) where T : UML_Base
{
while (reader.Read())
{
XDocument doc = XDocument.Load(this.filepath);
XNamespace ns = "http://www.yworks.com/xml/graphml";
XElement element = doc.Descendants(ns + "NodeLabel").FirstOrDefault();
string interfaceName = element.Value;
if (interfaceName.Contains("<<interface>>") || interfaceName.Contains("interface") || interfaceName.StartsWith("I") && interfaceName.Substring(0, 1).ToUpper().Equals(interfaceName))
{
UML_Interface interfaceModel = new UML_Interface(interfaceName, id);
return (T)Convert.ChangeType(interfaceModel, typeof(UML_Interface));
}
if (interfaceName != null && !interfaceName.Contains("<<interface>>") || !interfaceName.Contains("interface") || !interfaceName.StartsWith("I") && !interfaceName.Substring(0, 1).ToUpper().Equals(interfaceName))
{
UML_Class classModel = new UML_Class(interfaceName, id);
return (T)Convert.ChangeType(classModel, typeof(UML_Class));
}
}
return null;
}
我的问题是 XElement
只获得一个值,但有 3 个 <y:NodeLabel>
标签具有不同的值。对于值,我指的是文本。但是我的 XElement 对象 (from AnalyzeNodeLabel()
) 只是从第一个 <y:NodeLabel>
标签获取值,我如何添加其他标签?也许作为清单?或在一个循环后更新值?那可能吗?
你明确select节点的第一次出现:FirstOrDefault()
您必须 select 循环中的节点:
foreach (var element in doc.Descendants(ns + "NodeLabel"))
{
...
}
更新:
我不知道你为什么打开 Xml-File 两次或者 XmlReader.
发生了什么
如果您只对节点 "node" 和 "NodeLabel"(可能不止一个)感兴趣,那么这可能会有所帮助:
XNamespace yns = "http://www.yworks.com/xml/graphml";
Dictionary<string, List<string>> keys = new Dictionary<string, List<string>>();
foreach (var node in doc.Descendants(ns + "node"))
{
keys[node.Attribute("id").Value] = new List<string>();
foreach (var nodeLabel in node.Descendants(yns + "NodeLabel"))
{
keys[node.Attribute("id").Value].Add(nodeLabel.Value);
}
}
foreach (var entry in keys)
{
Console.WriteLine($"Key: {entry.Key}");
foreach (var basemodel in entry.Value)
{
Console.WriteLine($"->basemodel: {basemodel}");
}
}
输出为:
关键:n0
->basemodel: << interface >>Employee
关键:n1
->基础模型:客户
关键:n2
->基础模型:用户