In C#, I am trying to change an option of a feature in an XML file which presents a Print Ticket and loaded as an XElement
by the following code:
XElement ticketRootXElement = null;
using (Stream ticketReadStream = displayedPrintTicket.GetReadStream())
{
ticketRootXElement = XElement.Load(ticketReadStream);
}
The partial XML is something like following:
<?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>
How can I access the "Option" of a specific "Feature" and change it to something like <psf:Option name="psk:ISOA3">
?
I tried the following code, but it fails.
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());
}
}
}
}
You can can modify the option value of your selected feature as as follows:
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);
}
Notes:
XElement.Attribute(XName)
can be used to look up an attribute by name, and XElement.SetAttributeValue(XName, Object)
can be used to set or add an attribute value by name.
Casting an XAttribute
to a string
returns the value of the attribute, or null
if the attribute was missing, and so is convenient to use when filtering by attribute value in a where
statement.
If the selected <psf:Feature>
element does not have a child <psf:Option>
element, the above code will throw an exception. You will need to check your XML schema to determine whether this is possible, and if so, how to handle it.
Demo fiddle here.