提问人:Ryan Daley 提问时间:7/11/2022 最后编辑:FildorRyan Daley 更新时间:7/11/2022 访问量:68
XML Linq 查询中间的 If-Statement
If-Statement in the middle of XML Linq Query
问:
我知道关于 if 语句与 Linq 组合的类似线程已经存在,但在大多数情况下,他们建议在查询之前设置条件。就我而言,条件是查询中的 XML 元素。因此,我需要遍历所有父元素,并根据 Parent 包含的内容选择不同的子元素。
让我们看一下我的 xml 文件的示例。有两种不同类型的属性:Uda 和 Template。我需要获取两种类型的属性的名称(“TemplateName”或“UdaName”)。属性的结构彼此略有不同,因此我需要对每个属性进行略有不同的 Linq 查询。
<PropertySet referenceId="column_common">
<Name>Pset_ColumnCommon</Name>
<Description>Common Properties to column elements</Description>
<Properties>
<Property xsi:type="PropertySingleValueType" optional="true">
<PropertyValue xsi:type="StringValueType" stringType="IfcIdentifier">
<GetValue xsi:type="TemplateVariableType">
<TemplateName>PART_POS</TemplateName>
</GetValue>
</PropertyValue>
</Property>
<Property xsi:type="PropertySingleValueType" optional="true">
<PropertyValue xsi:type="BooleanValueType">
<ValueConversion xsi:type="BooleanTypeFromIntegerVariable">
<GetValue xsi:type="UdaVariableType">
<UdaName>LOAD_BEARING</UdaName>
</GetValue>
<KeyValuePair>
<Key>0</Key>
<Value>false</Value>
</KeyValuePair>
</ValueConversion>
<Default>true</Default>
</PropertyValue>
</Property>
</Properties>
</PropertySet>
如果它们都是 Template 属性,我可以简单地使用此 Linq 查询来获取 Names。
var propertyNames = from psetdefs in xElement.Elements(ns + "PropertySetDefinitions")
from pset in psetdefs.Elements(ns + "PropertySet")
where (string)pset.Attribute("referenceId").Value == PsetBinding
from props in pset.Elements(ns + "Properties")
from prop in props.Elements(ns + "Property")
from propValue in prop.Elements(ns + "PropertyValue")
from getValue in propValue.Elements(ns + "GetValue")
from templateName in getValue.Elements(ns + "TemplateName")
select templateName.Value;
我希望能够在 Linq 查询的中间放置一个 if 语句。这是我试图实现的逻辑,但显然它不起作用:
var propertyNames = from psetdefs in xElement.Elements(ns + "PropertySetDefinitions")
from pset in psetdefs.Elements(ns + "PropertySet")
where (string)pset.Attribute("referenceId").Value == PsetBinding
from props in pset.Elements(ns + "Properties")
from prop in props.Elements(ns + "Property")
from propValue in prop.Elements(ns + "PropertyValue")
if (propValue.Contains(ns + "ValueConverstion"))
{
from valCon in propValue.Elements(ns + "ValueConversion")
from getValue in valCon.Elements(ns + "GetValue")
from templateName in getValue.Elements(ns + "TemplateName")
select templateName.Value;
}
else
{
from getValue in propValue.Elements(ns + "GetValue")
from templateName in getValue.Elements(ns + "TemplateName")
select templateName.Value;
}
您可以看到它在树中有一个额外的元素,如果它是 UdaProperty。因此,查询变得不同。我该如何处理?
答:
0赞
Orace
7/11/2022
#1
最简单的方法是使用以下方法:DefaultIfEmpty
var propertyNames = from psetdefs in xElement.Elements(ns + "PropertySetDefinitions")
from pset in psetdefs.Elements(ns + "PropertySet")
where pset.Attribute("referenceId")?.Value == PsetBinding
from props in pset.Elements(ns + "Properties")
from prop in props.Elements(ns + "Property")
from propValue in prop.Elements(ns + "PropertyValue")
from valCon in propValue.Elements(ns + "ValueConverstion").DefaultIfEmpty(propValue)
from getValue in valCon.Elements(ns + "GetValue")
from templateName in getValue.Elements(ns + "TemplateName")
select templateName.Value;
另一种选择是使用三元运算符:
from valCon in (propValue.Contains("ValueConverstion") ? propValue.Elements(ns + "ValueConverstion") : new[] {propValue})
最后,XPath 更容易匹配您提供的示例文件。//GetValue/UdaName|//GetValue/TemplateName
评论
0赞
Orace
7/11/2022
它也不起作用,最终标签在第一种情况下和第二种情况下。TemplateName
UdaName
0赞
Ryan Daley
7/11/2022
伟大!这解决了我的问题!您的解决方案适用于这种特殊情况。但是,在 Linq 中是否有可以实现 if 语句逻辑的地方?我可以看到它在某些情况下很有用。
0赞
Ryan Daley
7/11/2022
我通过获取“GetValue”的所有子元素来使其工作。在这种情况下,这是有效的。
0赞
Orace
7/11/2022
不能放入 linq 查询,但可以调用可以放入查询的方法。也有错别字。 而不是if
ValueConverstion
ValueConversion
0赞
madreflection
7/11/2022
请记住,LINQ 是关于使用数据集的,因此子句是条件运算符,它应用于整个数据集。因此,您必须分组思考,以及如何按顺序处理每个元素。where
评论