将 xml 文件中的节点值设置为等于 C# 中节点的另一个值
Set the value of a node in xml file to be equal to another value of node in C#
假设我有以下 XML:
<?xml version="1.0" encoding="UTF-8" ?>
<exchange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://download.autodesk.com/us/navisworks/schemas/nw-exchange-12.0.xsd" units="ft" filename="" filepath="">
<batchtest name="3636" internal_name="3636" units="ft">
<clashtests>
<clashtest name="Ducts VS Ducts" test_type="hard" status="new" tolerance="0.0000000000" merge_composites="0">
<linkage mode="none"/>
<left>
<clashselection selfintersect="0" primtypes="1">
<locator>/</locator>
</clashselection>
</left>
<right>
<clashselection selfintersect="0" primtypes="1">
<locator>/</locator>
</clashselection>
</right>
<rules/>
</clashtest>
<clashtest name="Ducts VS Cable Trays" test_type="hard" status="new" tolerance="0.0000000000" merge_composites="0">
<linkage mode="none"/>
<left>
<clashselection selfintersect="0" primtypes="1">
<locator>/</locator>
</clashselection>
</left>
<right>
<clashselection selfintersect="0" primtypes="1">
<locator>/</locator>
</clashselection>
</right>
<rules/>
</clashtest>
</batchtest>
</exchange>
我想在 Visual Studio
中使用 C# 像这张图片一样
我想将 locator 节点的值更改为取决于 clash test 节点的值,如图所示。
使用xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
foreach (XElement clashtest in doc.Descendants("clashtest"))
{
string name = (string)clashtest.Attribute("name");
string pattern = "(?'name1'.*)VS(?'name2'.*)";
Match match = Regex.Match(name, pattern);
string name1 = match.Groups["name1"].Value.Trim();
string name2 = match.Groups["name2"].Value.Trim();
List<XElement> locators = clashtest.Descendants("locator").ToList();
locators[0].SetValue(name1);
locators[1].SetValue(name2);
}
}
}
}
var xml = XElement.Load("test.xml");
var clashtests = xml.Element("batchtest").Element("clashtests").Elements("clashtest");
foreach (var clashtest in clashtests)
{
string name = clashtest.Attribute("name").Value;
var values = name.Split(new[] { " VS " }, StringSplitOptions.None);
var left = clashtest.Element("left").Element("clashselection").Element("locator");
left.Value = values[0];
var right = clashtest.Element("right").Element("clashselection").Element("locator");
right.Value = values[1];
}
Console.WriteLine(xml);
指定完整路径:Element(...).Element(...)
比 Descendants
快。它对大型文档可能很重要。
XSLT 具有所谓的身份转换模式。
有用link:XSL Identity Transforms
下面的 XSLT 将按原样复制整个输入 XML,locator 元素除外。一旦找到 locator 元素,它将被替换为新的所需值。
XSLT 函数 substring-before()
和 substring-after()
可以轻松检索 name 属性值的所需部分。
您所要做的只是从您的 C# 代码中调用 XSLT 转换。
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" encoding="utf-8"/>
<!-- IdentityTransform -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="locator[parent::clashselection/parent::left]">
<locator>
<xsl:value-of select="substring-before(ancestor::clashtest/@name, ' VS')"/>
</locator>
</xsl:template>
<xsl:template match="locator[parent::clashselection/parent::right]">
<locator>
<xsl:value-of select="substring-after(ancestor::clashtest/@name, 'VS ')"/>
</locator>
</xsl:template>
</xsl:stylesheet>
假设我有以下 XML:
<?xml version="1.0" encoding="UTF-8" ?>
<exchange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://download.autodesk.com/us/navisworks/schemas/nw-exchange-12.0.xsd" units="ft" filename="" filepath="">
<batchtest name="3636" internal_name="3636" units="ft">
<clashtests>
<clashtest name="Ducts VS Ducts" test_type="hard" status="new" tolerance="0.0000000000" merge_composites="0">
<linkage mode="none"/>
<left>
<clashselection selfintersect="0" primtypes="1">
<locator>/</locator>
</clashselection>
</left>
<right>
<clashselection selfintersect="0" primtypes="1">
<locator>/</locator>
</clashselection>
</right>
<rules/>
</clashtest>
<clashtest name="Ducts VS Cable Trays" test_type="hard" status="new" tolerance="0.0000000000" merge_composites="0">
<linkage mode="none"/>
<left>
<clashselection selfintersect="0" primtypes="1">
<locator>/</locator>
</clashselection>
</left>
<right>
<clashselection selfintersect="0" primtypes="1">
<locator>/</locator>
</clashselection>
</right>
<rules/>
</clashtest>
</batchtest>
</exchange>
我想在 Visual Studio
中使用 C# 像这张图片一样我想将 locator 节点的值更改为取决于 clash test 节点的值,如图所示。
使用xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
foreach (XElement clashtest in doc.Descendants("clashtest"))
{
string name = (string)clashtest.Attribute("name");
string pattern = "(?'name1'.*)VS(?'name2'.*)";
Match match = Regex.Match(name, pattern);
string name1 = match.Groups["name1"].Value.Trim();
string name2 = match.Groups["name2"].Value.Trim();
List<XElement> locators = clashtest.Descendants("locator").ToList();
locators[0].SetValue(name1);
locators[1].SetValue(name2);
}
}
}
}
var xml = XElement.Load("test.xml");
var clashtests = xml.Element("batchtest").Element("clashtests").Elements("clashtest");
foreach (var clashtest in clashtests)
{
string name = clashtest.Attribute("name").Value;
var values = name.Split(new[] { " VS " }, StringSplitOptions.None);
var left = clashtest.Element("left").Element("clashselection").Element("locator");
left.Value = values[0];
var right = clashtest.Element("right").Element("clashselection").Element("locator");
right.Value = values[1];
}
Console.WriteLine(xml);
指定完整路径:Element(...).Element(...)
比 Descendants
快。它对大型文档可能很重要。
XSLT 具有所谓的身份转换模式。
有用link:XSL Identity Transforms
下面的 XSLT 将按原样复制整个输入 XML,locator 元素除外。一旦找到 locator 元素,它将被替换为新的所需值。
XSLT 函数 substring-before()
和 substring-after()
可以轻松检索 name 属性值的所需部分。
您所要做的只是从您的 C# 代码中调用 XSLT 转换。
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" encoding="utf-8"/>
<!-- IdentityTransform -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="locator[parent::clashselection/parent::left]">
<locator>
<xsl:value-of select="substring-before(ancestor::clashtest/@name, ' VS')"/>
</locator>
</xsl:template>
<xsl:template match="locator[parent::clashselection/parent::right]">
<locator>
<xsl:value-of select="substring-after(ancestor::clashtest/@name, 'VS ')"/>
</locator>
</xsl:template>
</xsl:stylesheet>