Linq to XML 命名空间问题
您好,
我的目标:验证 XML 文档,然后将数据加载到自定义对象中。我正在使用 Linq to XML。
我的情况:我在命名空间和/或 Linq 语法方面遇到了困难。我以为一切正常。该代码读取 XML 并加载对象,但意识到 XDocument.Validate 传递了所有内容,但并未真正进行验证。我猜这是验证不严格。为了验证 XDocument.Validate() 方法,我向 XML 文件添加了一个命名空间。验证有效,但现在尝试访问 .Element("Field").value 时,我的 Linq 查询创建的 XElement 返回 null。
我的问题:
- 如何验证 XML 文档并访问元素的值?除了使用 XDocument.Validate 之外,我还应该使用其他流程根据 XSD 验证 XML 吗?
- 问题出在我的 Linq 查询中吗?
当我尝试在 Linq 查询中指定特定元素时,我从未得到结果。它 仅当它有效时才有效
IEnumerable
;居民= 来自 xD.Elements() 中的 xeRes 选择 xeRes; 但是
IEnumerable
;居民= 来自 xD.Elements("Resident") 中的 xeRes 选择 xeRes;
不返回任何内容。
任何建议都将受到欢迎。
谢谢,
代码片段:
XSD
<?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns="http://kinduit.net/ResidentNS" xmlns:schema="http://kinduit.net/ResidentNS" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified"><xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="Resident">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="FacilityID">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ResidentID" maxOccurs="unbounded">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="20" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ResidentID2" maxOccurs="unbounded">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="20" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>...
XML
<?xml version="1.0"?><Resident xmlns="http://kinduit.net/ResidentNS">
<FacilityID>WARMSPRINGS</FacilityID>
<ResidentID>WS585459</ResidentID>
<ResidentID2>145214</ResidentID2>...
C#
// Validate XML Schema...
XmlSchemaSet sc = new XmlSchemaSet();
XNamespace xNs = "http://kinduit.net/ResidentNS";
try
{
// Validate against the XSD...
string location = System.Reflection.Assembly.GetAssembly(typeof(ElementsBC.Interface)).Location;
sc.Add(xNs.ToString(), location.Replace("ElementsBC.dll", "") + "\\InterfaceXSD\\resident.xsd");
XDocument xD = this.ConvertToXDocument(ResidentXML);
xD.Validate(sc, (sender, e) => { throw new Exception(e.Message); }, true);
IEnumerable<XElement> residents =
from xeRes in xD.Elements()
select xeRes;
counts[0] = residents.Count();
foreach (XElement el in residents)
{
try
{
// get facility...
string facilityid = el.Element("FacilityID").Value.ToString();
如果 XML 中有命名空间,最后一行将返回 null。如果没有命名空间,此代码将运行宽松的验证,但可以读取该值。
建议?
Greetings,
My goal: To validate an XML document then load the data into a custom object. I'm using Linq to XML.
My situation: I'm struggling with the Namespace and/or the Linq syntax. I thought everything was working. The code reads the XML and loads the object, but realized the XDocument.Validate was passing everything through and not really validating. I guess that's lax validation. To get the XDocument.Validate() method to validate, I added a Namespace to the XML file. The Validation works, but now the XElement created by my Linq Query returns null when trying to access .Element("Field").value.
My questions:
- How can I both validate the XML document and access the value of the Elements? Should I use another process to validate the XML against an XSD besides using XDocument.Validate?
- Is the problem in my Linq query?
When I try to specify a specific Element in the Linq query, I never get results. It
only works when it isIEnumerable<XElement> residents = from xeRes in xD.Elements() select xeRes;
but
IEnumerable<XElement> residents = from xeRes in xD.Elements("Resident") select xeRes;
returns nothing.
Any suggestions would be most welcome.
Thank you,
Code Snipets:
XSD
<?xml version="1.0" encoding="utf-8"?> <xsd:schema xmlns="http://kinduit.net/ResidentNS" xmlns:schema="http://kinduit.net/ResidentNS" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified"><xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
<xsd:element name="Resident">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="FacilityID">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ResidentID" maxOccurs="unbounded">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="20" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ResidentID2" maxOccurs="unbounded">
<xsd:simpleType>
<xsd:restriction base="sqltypes:varchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreKanaType IgnoreWidth" sqltypes:sqlSortId="52">
<xsd:maxLength value="20" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>...
XML
<?xml version="1.0"?><Resident xmlns="http://kinduit.net/ResidentNS">
<FacilityID>WARMSPRINGS</FacilityID>
<ResidentID>WS585459</ResidentID>
<ResidentID2>145214</ResidentID2>...
C#
// Validate XML Schema...
XmlSchemaSet sc = new XmlSchemaSet();
XNamespace xNs = "http://kinduit.net/ResidentNS";
try
{
// Validate against the XSD...
string location = System.Reflection.Assembly.GetAssembly(typeof(ElementsBC.Interface)).Location;
sc.Add(xNs.ToString(), location.Replace("ElementsBC.dll", "") + "\\InterfaceXSD\\resident.xsd");
XDocument xD = this.ConvertToXDocument(ResidentXML);
xD.Validate(sc, (sender, e) => { throw new Exception(e.Message); }, true);
IEnumerable<XElement> residents =
from xeRes in xD.Elements()
select xeRes;
counts[0] = residents.Count();
foreach (XElement el in residents)
{
try
{
// get facility...
string facilityid = el.Element("FacilityID").Value.ToString();
This last line returns null if there is a Namespace in the XML. If there is no Namespace, this code runs lax Validation, but can read the value.
Suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要在调用中包含名称空间。
you need to include the namespace in the call.
感谢蒂姆·贾维斯和碎玻璃。我结合他们的回答找到了答案。我对上面的代码遇到了三个问题。
请参阅下面更正的代码。
XSD
XML:无更改
C#
谢谢!
Thanks to Tim Jarvis and Broken Glass. I found the answer by combining their responses. I had three problems with the above code.
See corrected code below.
XSD
XML: no changes
C#
Thank you!
您必须声明并使用命名空间:
此外,您的 XML 中没有
Resident
元素 - 名为element
的元素具有属性name
不过,以“居民”开头。这些元素不是根节点的直接子节点,因此您必须在查询中使用Descendands()
而不是Elements()
。话虽如此,这对我有用(返回 3 个节点):
You have to declare and use a namespace:
Also there are no
Resident
elements in your XML - there are elements namedelement
that have an attributename
that starts with "Resident" though. These elements are not direct children of the root node so you have to useDescendands()
instead ofElements()
in your query.Having said that this works for me (returns 3 nodes):