[英]Bulk Editing Specific Elements in an XML with C#
我有一個 .xml 文件,它在兩個不同的元素之間共享一個屬性。 我試圖將一個元素中的屬性與一個變量相乘,並將另一個元素中的屬性與另一個變量相乘。
<acquirecosts>
<item>
<key>COST_SHOP_DEFAULT</key>
<quantity value="1"/>
<costtype>COST_TYPE_PRICE</costtype>
<items>
<item>
<item>CURRENCY_CASH</item>
<quantity value="6000"/>
</item>
</items>
<unlocks/>
</item>
</acquirecosts>
<sellprices>
<item>
<key>SELL_SHOP_DEFAULT</key>
<quantity value="1"/>
<costtype>COST_TYPE_PRICE</costtype>
<items>
<item>
<item>CURRENCY_CASH</item>
<quantity value="6000"/>
</item>
</items>
<unlocks/>
</item>
</sellprices>
<./acquirecosts> 中的“CURRENCY_CASH”數量值乘以 2,<./sellprices> 中的“CURRENCY_CASH”數量值乘以 0.5。
using System;
using System.Xml;
using System.Xml.XPath;
XmlDocument doc = new XmlDocument();
doc.Load(@"C:\Users\Darkye\Desktop\shopprices.xml");
var buyModifier = 2;
var sellModifier = 0.5;
var caItNodesBuy = caNode.XPathSelectElement("./acquirecosts").Elements();
foreach (var caItNodeBuy in caItNodesBuy)
{
var caItNodeItems = caItNodeBuy.XPathSelectElement("./items").Elements();
foreach (var item in caItNodeItems)
{
var caItNodeItemKey = item.Element("item").Value;
if (caItNodeItemKey != "CURRENCY_CASH") continue;
var caItNodeItemValue = (int)Math.Floor((double)int.Parse(item.Element("quantity").Attribute("value").Value) * buyModifier);
item.Element("quantity").SetAttributeValue("value", caItNodeItemValue);
}
caItNodeBuy.XPathSelectElement("./items").ReplaceNodes(caItNodeItems);
}
caNode.XPathSelectElement("./acquirecosts").ReplaceNodes(caItNodesBuy);
var caItNodesSell = caNode.XPathSelectElement("./sellprices").Elements();
foreach (var caItNodeSell in caItNodesSell)
{
var caItNodeItems = caItNodeSell.XPathSelectElement("./items").Elements();
foreach (var item in caItNodeItems)
{
var caItNodeItemKey = item.Element("item").Value;
if (caItNodeItemKey != "CURRENCY_CASH") continue;
var caItNodeItemValue = (int)Math.Floor((double)int.Parse(item.Element("quantity").Attribute("value").Value) * sellModifier);
item.Element("quantity").SetAttributeValue("value", caItNodeItemValue);
}
caItNodeSell.XPathSelectElement("./items").ReplaceNodes(caItNodeItems);
}
caNode.XPathSelectElement("./sellprices").ReplaceNodes(caItNodesSell);
但我正在努力弄清楚將“caNode”引入什么以及在何處引入。 我假設它是一個變量,但我已經迷失了。 將 caNode 更改為“doc”時,它只會在 XPathSelectElement 上引入錯誤。 除非有更簡單的方法在特定元素中應用這些編輯,否則我不確定還可以嘗試什么。
請嘗試以下解決方案。
它使用所謂的身份轉換模式。
它將根據所需的邏輯修改<quantity>
元素的@value
屬性值,而不會觸及任何其他內容。
輸入 XML
<root>
<acquirecosts>
<item>
<key>COST_SHOP_DEFAULT</key>
<quantity value="1"/>
<costtype>COST_TYPE_PRICE</costtype>
<items>
<item>
<item>CURRENCY_CASH</item>
<quantity value="6000"/>
</item>
</items>
<unlocks/>
</item>
</acquirecosts>
<sellprices>
<item>
<key>SELL_SHOP_DEFAULT</key>
<quantity value="1"/>
<costtype>COST_TYPE_PRICE</costtype>
<items>
<item>
<item>CURRENCY_CASH</item>
<quantity value="6000"/>
</item>
</items>
<unlocks/>
</item>
</sellprices>
</root>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="quantity">
<xsl:choose>
<xsl:when test="preceding-sibling::*='CURRENCY_CASH'">
<xsl:copy>
<xsl:attribute name="value">
<xsl:if test="ancestor::*[local-name() = 'acquirecosts']">
<xsl:value-of select="@value * 2"/>
</xsl:if>
<xsl:if test="ancestor::*[local-name() = 'sellprices']">
<xsl:value-of select="@value * 0.5"/>
</xsl:if>
</xsl:attribute>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
輸出 XML
<root>
<acquirecosts>
<item>
<key>COST_SHOP_DEFAULT</key>
<quantity value="1" />
<costtype>COST_TYPE_PRICE</costtype>
<items>
<item>
<item>CURRENCY_CASH</item>
<quantity value="12000" />
</item>
</items>
<unlocks />
</item>
</acquirecosts>
<sellprices>
<item>
<key>SELL_SHOP_DEFAULT</key>
<quantity value="1" />
<costtype>COST_TYPE_PRICE</costtype>
<items>
<item>
<item>CURRENCY_CASH</item>
<quantity value="3000" />
</item>
</items>
<unlocks />
</item>
</sellprices>
</root>
c#, XSLT 轉換
void Main()
{
const string SOURCEXMLFILE = @"e:\Temp\input.xml";
const string XSLTFILE = @"e:\Temp\process.xslt";
const string OUTPUTXMLFILE = @"e:\temp\output.xml";
try
{
XsltArgumentList xslArg = new XsltArgumentList();
using (XmlReader src = XmlReader.Create(SOURCEXMLFILE))
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(XSLTFILE, new XsltSettings(true, true), new XmlUrlResolver());
XmlWriterSettings settings = xslt.OutputSettings.Clone();
settings.IndentChars = "\t";
// to remove BOM
settings.Encoding = new UTF8Encoding(false);
using (XmlWriter result = XmlWriter.Create(OUTPUTXMLFILE, settings))
{
xslt.Transform(src, xslArg, result, new XmlUrlResolver());
result.Close();
}
}
Console.WriteLine("File '{0}' has been generated.", OUTPUTXMLFILE);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
使用 Xml Linq 並進行兩次傳遞
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement acquiredcosts = doc.Descendants("acquirecosts").FirstOrDefault();
List<XElement> currentCash = acquiredcosts.Descendants("item").Where(x => (string)x.Element("item") == "CURRENCY_CASH").ToList();
foreach (XElement c in currentCash)
{
XElement quantity = c.Element("quantity");
quantity.SetAttributeValue("value", 2 * (int)quantity.Attribute("value"));
}
XElement sellPrices = doc.Descendants("sellprices").FirstOrDefault();
currentCash = sellPrices.Descendants("item").Where(x => (string)x.Element("item") == "CURRENCY_CASH").ToList();
foreach (XElement c in currentCash)
{
XElement quantity = c.Element("quantity");
quantity.SetAttributeValue("value", .5 * (int)quantity.Attribute("value"));
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.