基于XML中StopSeg节点获取对应I_TP40B1节点的XPath或C#实现求助
解决方案
XPath 表达式
由于XML中StructuredText节点带有命名空间,提供两种写法:
方式1:忽略命名空间(简单快速)
//Component[@Name='StopSeg']/../../../../following-sibling::*[local-name()='Token' and @Text=':=']/following-sibling::*[local-name()='Access']/*[local-name()='Symbol']/*[local-name()='Component']
方式2:带命名空间的严谨写法
需先注册命名空间(前缀设为st,对应http://www.siemens.com/automation/Openness/SW/NetworkSource/StructuredText/v3):
//Component[@Name='StopSeg']/../../../../st:Token[@Text=':=']/following-sibling::st:Access/st:Symbol/st:Component
C# 代码实现
方法1:使用 XDocument(LINQ to XML)
using System; using System.Linq; using System.Xml.Linq; class Program { static void Main() { string xmlContent = @"<Document> <SW.Blocks.FC ID=""0""> <ObjectList> <SW.Blocks.CompileUnit ID=""4"" CompositionName=""CompileUnits""> <AttributeList> <NetworkSource> <StructuredText xmlns=""http://www.siemens.com/automation/Openness/SW/NetworkSource/StructuredText/v3""> <NewLine Num=""2"" UId=""116"" /> <Access Scope=""GlobalVariable"" UId=""117""> <Symbol UId=""118""> <Component Name=""TP40"" UId=""119"" /> <Token Text=""."" UId=""120"" /> <Component Name=""IN"" UId=""121"" /> <Token Text=""."" UId=""122"" /> <Component Name=""StopSeg"" UId=""123"" /> <Address Area=""None"" Type=""Bool"" BlockNumber=""3"" BitOffset=""3024"" Informative=""true"" /> </Symbol> </Access> <Blank Num=""29"" UId=""124"" /> <Token Text="":="" UId=""125"" /> <Blank Num=""1"" UId=""126"" /> <Access Scope=""GlobalVariable"" UId=""127""> <Symbol UId=""128""> <Component Name=""I_TP40B1"" UId=""129"" /> <Address Area=""Input"" Type=""Bool"" BitOffset=""1026"" Informative=""true"" /> </Symbol> </Access> <Token Text="";"" UId=""130"" /> <NewLine Num=""1"" UId=""131"" /> </StructuredText> </NetworkSource> </AttributeList> </SW.Blocks.CompileUnit> </ObjectList> </SW.Blocks.FC> </Document>"; XDocument doc = XDocument.Parse(xmlContent); XNamespace stNs = "http://www.siemens.com/automation/Openness/SW/NetworkSource/StructuredText/v3"; // 定位Name为StopSeg的Component节点 var stopSegComponent = doc.Descendants("Component") .FirstOrDefault(c => (string)c.Attribute("Name") == "StopSeg"); if (stopSegComponent != null) { // 找到所属的StructuredText父节点 var structuredText = stopSegComponent.Ancestors(stNs + "StructuredText").FirstOrDefault(); if (structuredText != null) { // 找到":="标记,再定位其后的Access节点下的Component var targetComponent = structuredText.Elements(stNs + "Token") .FirstOrDefault(t => (string)t.Attribute("Text") == ":=") ?.ElementsAfterSelf(stNs + "Access") .FirstOrDefault() ?.Element(stNs + "Symbol") ?.Element(stNs + "Component"); if (targetComponent != null) { Console.WriteLine($"目标Component的Name值: {(string)targetComponent.Attribute("Name")}"); } else { Console.WriteLine("未找到对应的Component节点"); } } } } }
方法2:使用 XmlDocument
using System; using System.Xml; class Program { static void Main() { string xmlContent = @"<Document> <SW.Blocks.FC ID=""0""> <ObjectList> <SW.Blocks.CompileUnit ID=""4"" CompositionName=""CompileUnits""> <AttributeList> <NetworkSource> <StructuredText xmlns=""http://www.siemens.com/automation/Openness/SW/NetworkSource/StructuredText/v3""> <NewLine Num=""2"" UId=""116"" /> <Access Scope=""GlobalVariable"" UId=""117""> <Symbol UId=""118""> <Component Name=""TP40"" UId=""119"" /> <Token Text=""."" UId=""120"" /> <Component Name=""IN"" UId=""121"" /> <Token Text=""."" UId=""122"" /> <Component Name=""StopSeg"" UId=""123"" /> <Address Area=""None"" Type=""Bool"" BlockNumber=""3"" BitOffset=""3024"" Informative=""true"" /> </Symbol> </Access> <Blank Num=""29"" UId=""124"" /> <Token Text="":="" UId=""125"" /> <Blank Num=""1"" UId=""126"" /> <Access Scope=""GlobalVariable"" UId=""127""> <Symbol UId=""128""> <Component Name=""I_TP40B1"" UId=""129"" /> <Address Area=""Input"" Type=""Bool"" BitOffset=""1026"" Informative=""true"" /> </Symbol> </Access> <Token Text="";"" UId=""130"" /> <NewLine Num=""1"" UId=""131"" /> </StructuredText> </NetworkSource> </AttributeList> </SW.Blocks.CompileUnit> </ObjectList> </SW.Blocks.FC> </Document>"; XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlContent); XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable); nsMgr.AddNamespace("st", "http://www.siemens.com/automation/Openness/SW/NetworkSource/StructuredText/v3"); // 通过XPath直接查询目标节点 XmlNode targetNode = doc.SelectSingleNode("//Component[@Name='StopSeg']/../../../../st:Token[@Text=':=']/following-sibling::st:Access/st:Symbol/st:Component", nsMgr); if (targetNode != null) { Console.WriteLine($"目标Component的Name值: {targetNode.Attributes["Name"].Value}"); } else { Console.WriteLine("未找到对应的Component节点"); } } }
内容的提问来源于stack exchange,提问作者Ankur
相关产品推荐
相关产品推荐

