簡體   English   中英

使用 C# 批量編輯 XML 中的特定元素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM