3

三部分问题。

是否可以通过其中的子节点定位特定的 XML 节点以检索父节点的其他子节点?例子:

<House>
    <Kitchen>
        <Appliance>
            <Name>Refrigerator</Name>
            <Brand>Maytag</Brand>
            <Model>F2039-39</Model>
        </Appliance>
        <Appliance>
            <Name>Toaster</Name>
            <Brand>Black and Decker</Brand>
            <Model>B8d-k30</Model>
        </Appliance>
    </Kitchen>
</House>

因此,为此,我想通过搜索“冰箱”或“烤面包机”来定位合适的设备节点,并从中检索品牌。

这个问题的第二部分是这样的:这是一种愚蠢的做法吗?在 Appliance 标签中使用属性会使这更容易吗?如果是这样,我将如何找到它?

至于第三部分,一旦我找到了设备,我将如何更改那个特定设备的型号?

4

4 回答 4

3

好吧,如果您使用的是 XmlDocument

foreach(XmlNode applianceNode in 
          myDocument.DocumentElement.SelectNodes("Kitchen/Applicance[Name='Refrigerator']")
{
   XmlNode modelNode = applicianceNode.SelectSingleNode("Model").InnerText = SomeOtherValue;
}

如果您将名称标签设为属性 (applicanceName),则对此几乎没有什么区别。

foreach(XmlNode applianceNode in 
          myDocument.DocumentElement.SelectNodes("Kitchen/Applicance[@applianceName='Refrigerator']")
{
// ...
}
于 2012-07-06T17:05:39.183 回答
3

使用Xlinq,您可以非常自然地执行此查询:

// Given:
//   var xdoc = XDocument.Load(...);
//   string applianceName = "Toaster";

// Find the appliance node who has a sub-element <Name> matching the appliance
var app = xdoc.Root
              .Descendants("Appliance")
              .SingleOrDefault(e => (string)e.Element("Name") == applianceName);

// If we've found one and it matches, make a change
if (app != null)
{
    if (((string)app.Element("Model")).StartsWith("B8d-k30"))
    {
        app.Element("Model").Value = "B8d-k30 Mark II";
    }
}

xdoc.Save(@"output.xml"); // save changes back to the document
于 2012-07-06T16:56:13.543 回答
0
    string xml = @"<House>
    <Kitchen>
        <Appliance>
            <Name>Refrigerator</Name>
            <Brand>Maytag</Brand>
            <Model>F2039-39</Model>
        </Appliance>
        <Appliance>
            <Name>Toaster</Name>
            <Brand>Black and Decker</Brand>
            <Model>B8d-k30</Model>
        </Appliance>
    </Kitchen>
</House>";

    XDocument xdoc = XDocument.Parse(xml);

    string newModel = "B8d-k45";

    var matchingElement = (from appliance in xdoc.Descendants("Appliance")
                           where appliance.Element("Name").Value == "Toaster"
                           select appliance).FirstOrDefault();

    if (matchingElement != null)
    {
        matchingElement.Element("Model").Value = newModel;
    }

    Console.WriteLine(xdoc.ToString());
于 2012-07-06T17:53:18.523 回答
0

死灵术。
是的,使用 XPath 更简单,并且完全没有 Linq 工作:
只需使用 .. 到达父节点(再想一想,使用“ordinalignorecase”时 Linq 会更容易)

public static void CreateNewHouse()
{
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
    doc.XmlResolver = null;
    doc.Load(@"d:\House.xml");

    foreach (System.Xml.XmlNode modelNode in doc.DocumentElement
.SelectNodes("/House/Kitchen/Appliance/Name[text()='Refrigerator']/../Model"))
    {
        modelNode.InnerText = "A New Value";
    }

    doc.Save(@"d:\MyHouse.xml");
}

我的房子.xml:

<House>
  <Kitchen>
    <Appliance>
      <Name>Refrigerator</Name>
      <Brand>Maytag</Brand>
      <Model>A New Value</Model>
    </Appliance>
    <Appliance>
      <Name>Toaster</Name>
      <Brand>Black and Decker</Brand>
      <Model>B8d-k30</Model>
    </Appliance>
  </Kitchen>
</House>

如果您需要它不区分大小写,请将 text() 替换为:

translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')

(仅适用于 ASCII/英语),当然也将“冰箱”更改为小写(“冰箱”)

如果 XML 文档有默认命名空间,则需要在 Select*Node 中提供它,例如

 xnImageTag.SelectSingleNode("./dft:Source", nsmgr);

在哪里

System.Xml.XmlNamespaceManager nsmgr = GetReportNamespaceManager(doc);

public static System.Xml.XmlNamespaceManager GetReportNamespaceManager(System.Xml.XmlDocument doc)
{
    if (doc == null)
        throw new ArgumentNullException("doc");

    System.Xml.XmlNamespaceManager nsmgr = new System.Xml.XmlNamespaceManager(doc.NameTable);

    // <Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">

    if (doc.DocumentElement != null)
    {
        string strNamespace = doc.DocumentElement.NamespaceURI;
        System.Console.WriteLine(strNamespace);
        nsmgr.AddNamespace("dft", strNamespace);
        return nsmgr;
    }

    nsmgr.AddNamespace("dft", "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition");
    // nsmgr.AddNamespace("dft", "http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition");

    return nsmgr;
} // End Function GetReportNamespaceManager
于 2015-03-25T15:05:02.607 回答