Linq to XML 命名空间问题

发布于 2024-10-31 02:17:32 字数 4206 浏览 0 评论 0原文

您好,

我的目标:验证 XML 文档,然后将数据加载到自定义对象中。我正在使用 Linq to XML。

我的情况:我在命名空间和/或 Linq 语法方面遇到了困难。我以为一切正常。该代码读取 XML 并加载对象,但意识到 XDocument.Validate 传递了所有内容,但并未真正进行验证。我猜这是验证不严格。为了验证 XDocument.Validate() 方法,我向 XML 文件添加了一个命名空间。验证有效,但现在尝试访问 .Element("Field").value 时,我的 Linq 查询创建的 XElement 返回 null。

我的问题

  1. 如何验证 XML 文档并访问元素的值?除了使用 XDocument.Validate 之外,我还应该使用其他流程根据 XSD 验证 XML 吗?
  2. 问题出在我的 Linq 查询中吗?
  3. 当我尝试在 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:

  1. 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?
  2. Is the problem in my Linq query?
  3. When I try to specify a specific Element in the Linq query, I never get results. It
    only works when it is

    IEnumerable<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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

决绝 2024-11-07 02:17:32

您需要在调用中包含名称空间。

XNamespace ns = xD.GetDefaultNamespace() // Or some other way of getting the namespace you want.
IEnumerable<XElement> residents = from xeRes in xD.Elements(ns + "Resident")        
                                  select xeRes;

you need to include the namespace in the call.

XNamespace ns = xD.GetDefaultNamespace() // Or some other way of getting the namespace you want.
IEnumerable<XElement> residents = from xeRes in xD.Elements(ns + "Resident")        
                                  select xeRes;
堇色安年 2024-11-07 02:17:32

感谢蒂姆·贾维斯和碎玻璃。我结合他们的回答找到了答案。我对上面的代码遇到了三个问题。

  1. 我在 XSD 中缺少 targetNamespace
  2. 我需要在 Linq 查询中添加命名空间,如 Tim Jarvis 和 Broken Glass 所示。
  3. 我需要在 XElement.Element 的 XName 参数中添加命名空间

请参阅下面更正的代码。

XSD

<?xml version="1.0" encoding="utf-8"?><xsd:schema xmlns:xs="http://kinduit.net/ResidentNS" targetNamespace="http://kinduit.net/ResidentNS" xmlns="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:无更改

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(xNs + "Resident")
                select xeRes;

            counts[0] = residents.Count();

            foreach (XElement el in residents)
            {
                try
                {
                    // get facility...
                    string facilityid = el.Element(xNs + "FacilityID").Value.ToString();

谢谢!

Thanks to Tim Jarvis and Broken Glass. I found the answer by combining their responses. I had three problems with the above code.

  1. I was missing the targetNamespace in the XSD.
  2. I needed to add the Namespace in my Linq query as indicated by Tim Jarvis and Broken Glass.
  3. I needed to add the Namespace in the XName parameter on XElement.Element.

See corrected code below.

XSD

<?xml version="1.0" encoding="utf-8"?><xsd:schema xmlns:xs="http://kinduit.net/ResidentNS" targetNamespace="http://kinduit.net/ResidentNS" xmlns="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: no changes

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(xNs + "Resident")
                select xeRes;

            counts[0] = residents.Count();

            foreach (XElement el in residents)
            {
                try
                {
                    // get facility...
                    string facilityid = el.Element(xNs + "FacilityID").Value.ToString();

Thank you!

↘人皮目录ツ 2024-11-07 02:17:32

您必须声明并使用命名空间:

XNamespace xsd = "http://www.w3.org/2001/XMLSchema";

此外,您的 XML 中没有 Resident 元素 - 名为 element 的元素具有属性 name不过,以“居民”开头。这些元素不是根节点的直接子节点,因此您必须在查询中使用 Descendands() 而不是 Elements()

话虽如此,这对我有用(返回 3 个节点):

XDocument xD = XDocument.Load("test.xml");
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";

IEnumerable<XElement> residents = from xeRes in xD.Descendants(xsd + "element")
                                  where xeRes.Attribute("name") != null 
                                  && xeRes.Attribute("name").Value.StartsWith("Resident") 
                                  select xeRes;

You have to declare and use a namespace:

XNamespace xsd = "http://www.w3.org/2001/XMLSchema";

Also there are no Resident elements in your XML - there are elements named element that have an attribute name that starts with "Resident" though. These elements are not direct children of the root node so you have to use Descendands() instead of Elements() in your query.

Having said that this works for me (returns 3 nodes):

XDocument xD = XDocument.Load("test.xml");
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";

IEnumerable<XElement> residents = from xeRes in xD.Descendants(xsd + "element")
                                  where xeRes.Attribute("name") != null 
                                  && xeRes.Attribute("name").Value.StartsWith("Resident") 
                                  select xeRes;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文