使用 C# 批量编辑 XML 中的特定元素

如何解决使用 C# 批量编辑 XML 中的特定元素

我有一个 .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>

<.>中的“CURRENCY_CASH”数量值乘以2,<.>中的“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"));
            }
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?