使用 XElement 访问 XML 文件中的子属性

Accessing a sub attribute in a XML file using XElement

在 C# 中,我试图更改 XML 文件中的一个功能选项,该文件显示打印票证并通过以下代码作为 XElement 加载:

XElement ticketRootXElement = null;
using (Stream ticketReadStream = displayedPrintTicket.GetReadStream())
{
   ticketRootXElement = XElement.Load(ticketReadStream);
}

部分 XML 如下所示:

<?xml version="1.0"?>
<psf:Feature xmlns:psf="http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" name="psk:PageMediaSize">
    <psf:Option name="psk:ISOA4">
        <psf:ScoredProperty name="psk:MediaSizeWidth">
            <psf:Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:integer">210000</psf:Value>
        </psf:ScoredProperty>
        <psf:ScoredProperty name="psk:MediaSizeHeight">
            <psf:Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:integer">297000</psf:Value>
        </psf:ScoredProperty>
    </psf:Option>
</psf:Feature>

如何访问特定 "Feature" 的 "Option" 并将其更改为类似
<psf:Option name="psk:ISOA3"> 的内容?

我尝试了下面的代码,但是失败了。

foreach (XAttribute xAttr in ticketRootXElement.Descendants(xns_psf + "Feature").Attributes())
{
   if (xAttr.Value.Equals("psk:PageMediaSize"))
   {
      foreach(XAttribute xSubAttr in ticketRootXElement.Element("PageMediaSize").Descendants(xns_psf + "Option").Attributes())
      {
         if (xAttr.NextAttribute.Name.LocalName.Equals("name"))
         {
            xAttr.NextAttribute.SetValue("psk:ISO" + cmb_PaperSize.SelectedValue.ToString());
         }
      }
   }
}

您可以修改所选功能的选项值,如下所示:

var featureName = "psk:PageMediaSize";
var newOptionValue = "psk:ISOA3"; // Your modified value here

XNamespace xns_psf = @"http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework";
var query = from f in ticketRootXElement.DescendantsAndSelf(xns_psf + "Feature")
            where (string)f.Attribute("name") == featureName
            select f;
foreach (var f in query)
{
    // TODO: handle the situation were a child <psf:Option> element is missing.
    f.Element(xns_psf + "Option").SetAttributeValue("name", newOptionValue);
}

备注:

  • XElement.Attribute(XName) can be used to look up an attribute by name, and XElement.SetAttributeValue(XName, Object) 可用于按名称设置或添加属性值。

  • Casting XAttributestring returns 属性的值,或者 null 如果属性丢失, 因此在 where 语句中按属性值过滤时使用起来很方便。

  • 如果选择的<psf:Feature>元素没有子<psf:Option>元素,上面的代码会抛出异常。您将需要检查您的 XML 架构以确定这是否可行,如果可行,如何处理。

演示 fiddle here.

实际上我是用下面的代码做的。但是 "bdc" 解决方案(以上答案)听起来好多了:

var element = ticketRootXElement.Descendants(xns_psf + "Feature")
              .Where(arg => arg.Attribute("name").Value == "psk:PageMediaSize")
              .Single();

var subelement = element.Descendants(xns_psf + "Option")
                .Single();

subelement.FirstAttribute.SetValue("psk:ISOA3");