Linq到XML Namespace的问题

时间:2011-04-05 23:01:06

标签: xml linq linq-to-xml

问候,

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

我的情况:我正在努力使用命名空间和/或Linq语法。我以为一切都在运作。代码读取XML并加载对象,但实现了XDocument.Validate传递了所有内容而没有真正验证。我想那是松懈的验证。为了使XDocument.Validate()方法有效,我在XML文件中添加了一个Namespace。验证工作正常,但现在我的Linq查询创建的XElement在尝试访问.Element(“Field”)时返回null。值。

我的问题:

  1. 我如何验证XML文档并访问Elements的值?除了使用XDocument.Validate之外,我是否应该使用另一个进程来针对XSD验证XML?
  2. 我的Linq查询中存在问题吗?
  3. 当我尝试在Linq查询中指定特定元素时,我从未得到结果。它 只有在

    时才有效
    IEnumerable<XElement> residents =
            from xeRes in xD.Elements()
            select xeRes;
    

    IEnumerable<XElement> residents =
            from xeRes in xD.Elements("Resident")
            select xeRes;
    
  4. 什么都不返回。

    欢迎任何建议。

    谢谢,

    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();
    

    如果XML中有名称空间,则最后一行返回null。如果没有命名空间,则此代码运行不严格的验证,但可以读取值。

    建议?

3 个答案:

答案 0 :(得分:1)

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

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;

答案 1 :(得分:1)

感谢Tim Jarvis和Broken Glass。我通过结合他们的回答找到答案。我在上面的代码中遇到了三个问题。

  1. 我错过了XSD中的 targetNamespace
  2. 我需要在我的Linq查询中添加命名空间,如Tim Jarvis和Broken Glass所示。
  3. 我需要在XElement.Element上的XName参数中添加命名空间
  4. 请参阅下面的更正代码。

    <强> 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();
    

    谢谢!

答案 2 :(得分:0)

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

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

此外,您的XML中没有Resident元素 - 有些名为element的元素具有以“Resident”开头的属性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;