命名空间遍历

时间:2012-10-16 15:35:03

标签: c# xml xpath

我正在尝试解析以下XML示例:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soapenv:Body>
        <d2LogicalModel modelBaseVersion="1.0" xmlns="http://datex2.eu/schema/1_0/1_0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://datex2.eu/schema/1_0/1_0 http://datex2.eu/schema/1_0/1_0/DATEXIISchema_1_0_1_0.xsd">
            <payloadPublication xsi:type="PredefinedLocationsPublication" lang="en">
                <predefinedLocationSet id="GUID-NTCC-VariableMessageSignLocations">
                    <predefinedLocation id="VMS30082775">
                        <predefinedLocationName>    
                            <value lang="en">VMS M60/9084B</value>
                        </predefinedLocationName>
                    </predefinedLocation>
                </predefinedLocationSet>
            </payloadPublication>
        </d2LogicalModel>
    </soapenv:Body>
</soapenv:Envelope>

我特别需要获取顶级的predefinedLocation标记的内容。根据我的计算,正确的XPath应该是

/soapenv:Envelope/soapenv:Body/d2LogicalModel/payloadPublication/predefinedLocationSet/predefinedLocation

我使用以下C#代码来解析XML:             string filename =“content-sample.xml”;

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(filename);

        XmlNamespaceManager nsmanager = new XmlNamespaceManager(xmlDoc.NameTable);
        nsmanager.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/Envelope");

        string xpath ="/soapenv:Envelope/soapenv:Body/d2LogicalModel/payloadPublication/predefinedLocationSet/predefinedLocation";
        XmlNodeList itemNodes = xmlDoc.SelectNodes(xpath, nsmanager);

然而,这一直没有结果。任何人都可以对此有所了解,因为我觉得我正在敲打砖墙。

4 个答案:

答案 0 :(得分:2)

d2LogicalModel及其后代不在空命名空间中,而是在“http://datex2.eu/schema/1_0/1_0”命名空间中。您需要将此命名空间添加到命名空间管理器,以便能够选择元素:

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.Load(filename); 

XmlNamespaceManager nsmanager = new XmlNamespaceManager(xmlDoc.NameTable); 
nsmanager.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/Envelope"); 
nsmanager.AddNamespace("dataexNs", "http://datex2.eu/schema/1_0/1_0"); 


string xpath ="/soapenv:Envelope/soapenv:Body/dataexNs:d2LogicalModel/dataexNs:payloadPublication/dataexNs:predefinedLocationSet/dataexNs:predefinedLocation"; 
XmlNodeList itemNodes = xmlDoc.SelectNodes(xpath, nsmanager); 

即使您使用Linq到Xml,也值得使用完全限定名称来选择不具有相同本地名称的内容。

答案 1 :(得分:1)

如果你想避免处理命名空间(使用Linq2Xml)

var xDoc = XDocument.Load(.....);

var loc = xDoc.Root.Descendants2("predefinedLocation").First();
var id = loc.Attribute("id");
var value = loc.Descendants2("value").First().Value;


public static class S_O_Extensions
{
    public static IEnumerable<XElement> Descendants2(this XElement xRoot, string name)
    {
        return xRoot.Descendants().Where(n => n.Name.LocalName == name);
    }
}

答案 2 :(得分:0)

我猜这 LINQ2XML 会帮助你解决问题

XElement doc = XElement.Load("yourStream.xml");
XNamespace s="http://datex2.eu/schema/1_0/1_0";

foreach (var itm in doc.Descendants(s+ "predefinedLocation"))
{
itm;//your required predefinedLocationName node 
itm.Element(s+"predefinedLocationName").Element(s+"value").Value;//VMS M60/9084B
}

答案 3 :(得分:0)

说到XPath,我总是发现更小/更短/更简单的XPath表达式更好。我会用这个:

//predefinedLocationSet

这对你有用吗?在XPath测试仪上,它确实对我有用。