C#:如何从 Xml 文件中按值 select 单个节点(元素?)?
C# : How to select a single node (element?) from an Xml file by value?
我是 Xml 的新手,正在尝试创建一个我可以从相应的 C# 控制台应用程序读取和写入的简单数据库。
我加载了 Xml 文件,然后生成 Xml 元素的 C# 列表 'string_ID'(希望成为每个节点中的标识符 - 将显示代码 * * 注意:不是实际的 Xml ID 功能)。如果用户输入与列表中的 string_ID 匹配(我假设我可以删除这部分,但这基本上是我问题的核心),那么程序会选择相应的 Xml 元素并递增计数节点(?).
我无法根据用户输入选择单个节点来工作。好吧,我根本无法让基于 "string_ID" 的单节点选择工作——就像硬编码我的测试值一样。
我之前在网上找到的一些尝试:
1)
XmlElement root = xDoc.DocumentElement;
var result = root.GetElementsByTagName("prizeUnit")
.Where(i => (string)i.Element("string_ID") == "333AI")
.Seelect(i => (string)i.Element("Folder"));
- 我最近的; .where等连注册都不用了
2)
XmlNode node = xDoc.DocumentElement.SelectSingleNode(
'//prizeUnit/string_ID[text()="333AI"]');
- 注意单引号与双引号。
3)
XmlNode node = xDoc.DocumentElement.SelectSingleNode(
"root_prizes/prizeUnit/string_ID[" + input + "]");
4)
XmlNode node = xDoc.DocumentElement.SelectSingleNode(
"root_prizes/prizeUnit/[string_ID/text() = \"input\"]");
- 这是案例 #2 之前的案例。 \" \" 对我来说似乎值得注意。
我的 Xml 文件:
<root_prizes xmlns="http://tempuri.org/XMLSchema.xsd">
<prizeUnit>
<string_ID>333AI</string_ID>
<prizeName>cashGrandPrize01</prizeName>
<count>1313</count>
</prizeUnit>
<prizeUnit>
<string_ID>334BI</string_ID>
<prizeName>cashGrandPrize02</prizeName>
<count>2424</count>
</prizeUnit>
<prizeUnit>
<string_ID>335CI</string_ID>
<prizeName>cashGrandPrize03</prizeName>
<count>0</count>
</prizeUnit>
</root_prizes>
我对上述文件的架构(我刚刚进入架构,如果其中有明显的问题,我深表歉意):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="root_prizes">
<xs:complexType>
<xs:sequence>
<!--
<xs:element name="prizeUnit" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="string_ID" type="xs:string" />
<xs:element name="prizeName" type="xs:string" />
<xs:element name="count" type="xs:integer" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
用户输入的字符串应对应于"string_ID",即'335AI'。
对于案例 #3,我遇到了错误:
未处理的异常:System.Xml.XPath.XPathException:表达式必须求值为节点集。
感谢您的所有帮助。
在 XPath 的帮助下 docs 我已经为您构建了一个解决方案
//if you have non-empty xmlns tag you have to use namespace manager
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ps", "http://tempuri.org/XMLSchema.xsd");
string id = "334BI";
XmlNode node = doc.SelectSingleNode($"/ps:root_prizes/ps:prizeUnit[ps:string_ID='{id}']", nsmgr);
//another of possible solutions
//XmlNode node = doc.SelectSingleNode($"descendant::ps:prizeUnit[ps:string_ID='{id}']", nsmgr);
如果您有一个空 xmlns
标签或根本没有标签,以下解决方案也适用
XmlNode node = doc.SelectSingleNode($"/root_prizes/prizeUnit[string_ID='{id}']");
我是 Xml 的新手,正在尝试创建一个我可以从相应的 C# 控制台应用程序读取和写入的简单数据库。
我加载了 Xml 文件,然后生成 Xml 元素的 C# 列表 'string_ID'(希望成为每个节点中的标识符 - 将显示代码 * * 注意:不是实际的 Xml ID 功能)。如果用户输入与列表中的 string_ID 匹配(我假设我可以删除这部分,但这基本上是我问题的核心),那么程序会选择相应的 Xml 元素并递增计数节点(?).
我无法根据用户输入选择单个节点来工作。好吧,我根本无法让基于 "string_ID" 的单节点选择工作——就像硬编码我的测试值一样。
我之前在网上找到的一些尝试:
1)
XmlElement root = xDoc.DocumentElement;
var result = root.GetElementsByTagName("prizeUnit")
.Where(i => (string)i.Element("string_ID") == "333AI")
.Seelect(i => (string)i.Element("Folder"));
- 我最近的; .where等连注册都不用了
2)
XmlNode node = xDoc.DocumentElement.SelectSingleNode(
'//prizeUnit/string_ID[text()="333AI"]');
- 注意单引号与双引号。
3)
XmlNode node = xDoc.DocumentElement.SelectSingleNode(
"root_prizes/prizeUnit/string_ID[" + input + "]");
4)
XmlNode node = xDoc.DocumentElement.SelectSingleNode(
"root_prizes/prizeUnit/[string_ID/text() = \"input\"]");
- 这是案例 #2 之前的案例。 \" \" 对我来说似乎值得注意。
我的 Xml 文件:
<root_prizes xmlns="http://tempuri.org/XMLSchema.xsd">
<prizeUnit>
<string_ID>333AI</string_ID>
<prizeName>cashGrandPrize01</prizeName>
<count>1313</count>
</prizeUnit>
<prizeUnit>
<string_ID>334BI</string_ID>
<prizeName>cashGrandPrize02</prizeName>
<count>2424</count>
</prizeUnit>
<prizeUnit>
<string_ID>335CI</string_ID>
<prizeName>cashGrandPrize03</prizeName>
<count>0</count>
</prizeUnit>
</root_prizes>
我对上述文件的架构(我刚刚进入架构,如果其中有明显的问题,我深表歉意):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="root_prizes">
<xs:complexType>
<xs:sequence>
<!--
<xs:element name="prizeUnit" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="string_ID" type="xs:string" />
<xs:element name="prizeName" type="xs:string" />
<xs:element name="count" type="xs:integer" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
用户输入的字符串应对应于"string_ID",即'335AI'。
对于案例 #3,我遇到了错误: 未处理的异常:System.Xml.XPath.XPathException:表达式必须求值为节点集。
感谢您的所有帮助。
在 XPath 的帮助下 docs 我已经为您构建了一个解决方案
//if you have non-empty xmlns tag you have to use namespace manager
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ps", "http://tempuri.org/XMLSchema.xsd");
string id = "334BI";
XmlNode node = doc.SelectSingleNode($"/ps:root_prizes/ps:prizeUnit[ps:string_ID='{id}']", nsmgr);
//another of possible solutions
//XmlNode node = doc.SelectSingleNode($"descendant::ps:prizeUnit[ps:string_ID='{id}']", nsmgr);
如果您有一个空 xmlns
标签或根本没有标签,以下解决方案也适用
XmlNode node = doc.SelectSingleNode($"/root_prizes/prizeUnit[string_ID='{id}']");