C#项目中如何用XPath同时提取不同层级的Name与TemplateName
问题:在C#中用XPath同时提取PropertySet的Name和TemplateName
我在C#项目里使用XPath,需要为每个PropertySet提取树形结构中不同层级的两个值:
PropertySet节点下的Name- 其下属
Property节点里GetValue下的TemplateName
请问能否通过XPath同时返回这两个值?期望遍历所有PropertySet并获取每个属性集对应的这两个名称。
XML结构示例
<PropertySetDefinitions> <PropertySet referenceId="Common"> <Name>Tekla Common</Name> <Description>Common Properties to Shared building elements</Description> <Properties> <Property xsi:type="PropertySingleValueType" optional="true"> <Name>Class</Name> <PropertyValue xsi:type="StringValueType" stringType="IfcLabel"> <GetValue xsi:type="TemplateVariableType"> <TemplateName>CLASS_ATTR</TemplateName> </GetValue> </PropertyValue> </Property> </Properties> </PropertySet> </PropertySetDefinitions>
当前仅提取TemplateName的C#代码
XPathNavigator nav; XPathDocument docNav; XPathNodeIterator NodeIterator; string strExpression; string res = string.Empty; docNav = new XPathDocument(ifcExportSettings); nav = docNav.CreateNavigator(); XmlNamespaceManager mgr = new XmlNamespaceManager(nav.NameTable); mgr.AddNamespace("tu", @"http://www.tekla.com/IfcProperties"); strExpression = $"/tu:PropertySetConfiguration" + $"/tu:PropertySetDefinitions" + $"/tu:PropertySet[@referenceId='{set}']" + $"/tu:Properties/tu:Property[not(/tu:ValueConversion)]/tu:PropertyValue/tu:GetValue/tu:TemplateName";
解决方案
当然可以实现,核心是先定位到能关联两个值的父节点,再分别提取对应内容,以下是两种实用方法:
方法1:遍历Property节点,关联所属PropertySet的Name
这种方法适合PropertySet下有多个Property的场景,能精准对应每个TemplateName到所属的PropertySet名称:
XPathNavigator nav; XPathDocument docNav; XPathNodeIterator propertyIterator; string strExpression; docNav = new XPathDocument(ifcExportSettings); nav = docNav.CreateNavigator(); XmlNamespaceManager mgr = new XmlNamespaceManager(nav.NameTable); mgr.AddNamespace("tu", @"http://www.tekla.com/IfcProperties"); // 定位到符合条件的Property节点 strExpression = $"/tu:PropertySetConfiguration" + $"/tu:PropertySetDefinitions" + $"/tu:PropertySet[@referenceId='{set}']" + $"/tu:Properties/tu:Property[not(tu:ValueConversion)]"; propertyIterator = nav.Select(strExpression, mgr); while (propertyIterator.MoveNext()) { // 获取当前Property所属的PropertySet的Name var propertySetName = propertyIterator.Current.SelectSingleNode("../../../tu:Name", mgr)?.Value; // 获取当前Property对应的TemplateName var templateName = propertyIterator.Current.SelectSingleNode("tu:PropertyValue/tu:GetValue/tu:TemplateName", mgr)?.Value; // 此处可根据需求处理结果,比如输出、存储 Console.WriteLine($"PropertySet名称:{propertySetName},Template名称:{templateName}"); }
方法2:XPath 2.0+ 直接返回拼接值(适合简单场景)
如果你的开发环境支持XPath 2.0(比如使用XDocument配合XPathSelectElements,或第三方库如Saxon),可以用concat函数直接拼接两个值,后续再拆分:
/tu:PropertySetConfiguration/tu:PropertySetDefinitions/tu:PropertySet[@referenceId='{set}']/concat(tu:Name, '|', tu:Properties/tu:Property[not(tu:ValueConversion)]/tu:PropertyValue/tu:GetValue/tu:TemplateName)
关键注意点
- 确保XML命名空间与代码中定义的
tu前缀完全一致; - 若只需每个
PropertySet的名称和其下所有TemplateName的集合,可直接遍历PropertySet节点,再批量提取下属的TemplateName。
内容的提问来源于stack exchange,提问作者Ryan Daley
相关产品推荐
相关产品推荐

