如何在C#中使用一个XML文件中的信息创建另一个XML文件?

3
我是一个有用的助手,可以将文本翻译成中文。
我有一个非常大的XML文件,其中包含一些我感兴趣的信息,但我需要以另一种方式呈现它。让我举个例子:
源XML
<root attribute1="something" attribute2="somethingelse">
<items>
  <item id="dontcare" name="Need This Name 1" url="http://NeedThisUrl1.com">
    <availability>
      <instores/>
    </availability>
  </item>
  <item id="dontcare" name="Need This Name 2" url="http://NeedThisUrl2.com">
    <availability>
      <instores/>
    </availability>
  </item>
</items>
</root>

结果 XML
<Items>
    <Item Attribute1="HardcodedValue1" Attribute2="HardcodedValue2">
      <Parameter Name="Id">Hardcoded Value</Parameter>
      <Parameter Name="Name">Need This Name 1</Parameter>
      <Parameter Name="Url">http://NeedThisUrl1.com</Parameter>
      <Parameter Name="Availability">Hardcoded Value</Parameter>
    </Item>
    <Item Attribute1="HardcodedValue1" Attribute2="HardcodedValue2">
      <Parameter Name="Id">Hardcoded Value</Parameter>
      <Parameter Name="Name">Need This Name 2</Parameter>
      <Parameter Name="Url">http://NeedThisUrl2.com</Parameter>
      <Parameter Name="Availability">Hardcoded Value</Parameter>
    </Item>
</Items>

我该如何在C#中实现这个?

最好使用Linq来处理XML。有很多示例可供参考。您需要获取xdoc.Elements("items")的所有元素,然后将属性转换为新文档中的元素。 - Dweeberly
4个回答

3

我最终选择了这个。我怎么会不知道XSLT呢?谢谢。 - Freakishly
@Freakishly 总有一些我们不知道的东西,这就是其中的乐趣 ;) - OnoSendai

2
你可以使用C#内置的Xml类来处理它。使用Linq也会很有帮助。
以下是获取值的代码。你可以扩展它以使用Linq,我将在下面为中级水平进行解释(但是你上面的示例不需要,因为第三级不需要)。
internal static LoadIndividualItem(XElement xelement)
{
    XElement element = ; //you need to pass the document as an Xelement somehow

    foreach (XElement child in element.Elements())
                {
                    string elementName = child.Name.ToString();

                    if (string.Compare(elementName, "item", true) == 0)
                    {
                        string name = child.Attribute(XName.Get("name"));
                        // Do something with this string

                        string name = child.Attribute(XName.Get("url"));
                        // Do something with this string\
                    }
                }
}

这是获取XElement的示例:
public void LoadFromFile(string sourcXmlFileName = null)
{
    // Checks to see if file has been specified, if not assign it to the default value
    if (string.IsNullOrEmpty(sourceXmdlFileName))
        sourceXmdlFileName = DefaultInventoryFile;

    // Check to make sure the file is there
        if (!File.Exists(sourceXmdlFileName))
            return;

    List<ObjectToHoldValues> MasterObject = new List<ObjectToHoldValues>();

            using (TextReader reader = new StreamReader(sourceXmlFileName, Encoding.UTF8))
            {
                // Create an xml document and assign it to a local variable
                XDocument doc = XDocument.Load(reader);

                // Load the roots
                foreach (XElement element in doc.Descendants("root"))
                {
                    ObjectToHoldValues itemList = new ObjectToHoldValues();
                    itemList = LoadIndividualItem(element);

                    MasterObject.Add(itemList);
                }
            }
}

您需要创建不同的控制器,从根开始使用Linq向下移动每个对象,在标签内添加不同的元素。底层标记可能如下所示。
internal static LowLevelItem LowLevelFromXml(XElement element)
{
        return (
            // Create the Inventory item node
            new XElement("BottomLevel",
                // Create each child node of the values you need
                new XElement("ValueOne", _valueOne.ToString())
               ,new XElement("ValueTwo", _valueTwo));
}

中级对象可能看起来像这样:

中级对象可能看起来像这样

internal static MidLevelItem MidLevelItemFromXml(XElement element)
{
            XElement Root = new XElement("MidLevel");

            //Add all of the individual lower level records to the this root
            Root.Add(_lowerLevelItems
                .Select(item => item.LowLevelFromXml())
                .ToArray());

            return Root;
}

顶层可能看起来像这样:
public void Save(string targetXmlFileName = null)
{
            XDocument doc = new XDocument();
            XElement root = new XElement("TopLevel");

            //Add the root to the XML document
            doc.Add(root);

            //Add all of the subitems records to the XML document
            root.Add(_midLevelItem
                .Select(item => item.MidLevelItemFromXml())
                .ToArray());

            var settings = new XmlWriterSettings()
            {
                CloseOutput = true,
                Indent = true,
                Encoding = Encoding.UTF8
            };

            // Write the XML file
            using (XmlWriter writer = XmlWriter.Create(targetXmlFileName ?? DefaultFile, settings))
            {
                doc.Save(writer);
            }
}

好的,我明白如何将输入的XML文件转换为 List<ObjectToHoldValues> MasterObject,但我无法理解 root.Add(_midLevelItem...)部分。您在哪里调用MidLevelItemFromXml? - Freakishly
我从一个我写过的文件中拿到了这个。那里的方法都被命名为ToXmlElement。我在这里进行了更正。 - Recursor

0
假设我们有一个如下所示的XSLT文件,它将用于格式化XML文档。
    <?xml version="1.0" encoding="utf-8"?>
       <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo='http://www.w3.org/1999/XSL/Format'
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
   <xsl:output method="xml" indent="yes"/>
 <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@`enter code here`* | node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="/ReportTable">
    <fo:root>
      <fo:layout-master-set>
        <fo:simple-page-master master-name="all-pages" page-width="8.27in" page-height="11.69in">
          <fo:region-body region-name="xsl-region-body" margin-left="0.7in" margin-right="0.7in" margin-top="0.7in" margin-bottom="0.7in" column-gap="0.25in" />
          <fo:region-before region-name="xsl-region-before" extent="0.7in" display-align="after" padding-left="0.7in" padding-right="0.7in" margin-top="0.2in"  margin-bottom="0.4in"/>
          <fo:region-after region-name="xsl-region-after" extent="0.7in" padding-left="0.7in" padding-right="0.7in" margin-top="0.2in"  margin-bottom="0.1in"/>
        </fo:simple-page-master>
        <fo:page-sequence-master master-name="default-sequence">
          <fo:repeatable-page-master-reference master-reference="all-pages" />
        </fo:page-sequence-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="default-sequence">
        <fo:static-content flow-name="xsl-region-before" >
          <fo:block  text-align="center" font-weight="bold" text-decoration="underline" line-height="200%">Page Title</fo:block>
          <fo:block line-height="70%" >
            &#x00A0;
          </fo:block>
          <fo:block line-height="200%">
            <!--to increase height  between line and Header -->

              <fo:table border-collapse="collapse" width="100%" table-layout="fixed">
              <fo:table-column column-width="proportional-column-width(15.0)" column-number="1"/>
              <fo:table-column column-width="proportional-column-width(45.0)" column-number="2"/>
              <fo:table-column column-width="proportional-column-width(25.0)" column-number="3"/>
              <fo:table-column column-width="proportional-column-width(15.0)" column-number="4"/>
              <fo:table-body>
                <fo:table-row>
                  <fo:table-cell >
                    <fo:block text-align="center">
                      <fo:inline font-weight="bold" text-align="center">
                        <xsl:value-of select="Node1"></xsl:value-of>
                      </fo:inline>
                    </fo:block>
                  </fo:table-cell>
                  <fo:table-cell >
                    <fo:block text-align="left">
                      <fo:inline text-align="left">
                        <xsl:value-of select="Node2"></xsl:value-of>
                      </fo:inline>
                    </fo:block>
                  </fo:table-cell>
                  <fo:table-cell >
                    <fo:block text-align="right">
                      <fo:inline font-weight="bold" text-align="right">
                        <xsl:value-of select="Node3"></xsl:value-of>
                      </fo:inline>
                    </fo:block>
                  </fo:table-cell>
                  <fo:table-cell >
                    <fo:block text-align="left">
                      <fo:inline text-align="left">
                        <xsl:value-of select="Node4"></xsl:value-of>
                      </fo:inline>
                    </fo:block>
                  </fo:table-cell>
                </fo:table-row>  
              </fo:table-body>
            </fo:table>&#x00A0; 
          </fo:block>
        </fo:static-content>
        <fo:static-content flow-name="xsl-region-after" >
          <fo:block line-height="200%">
            <!--to increase height between line and footer-->
            <fo:table border-collapse="collapse" width="100%" table-layout="fixed" border-top-width="1pt" border-top-style="solid" border-top-color="rgb(0,0,0)">
              <fo:table-column column-width="proportional-column-width(50)" column-number="1"/>
              <fo:table-column column-width="proportional-column-width(50)" column-number="2"/>
              <fo:table-body>
                <fo:table-row>
                  <fo:table-cell >
                    <fo:block text-align="center">
                      <fo:inline font-weight="bold" text-align="center">
                        Page <fo:page-number/> of <fo:page-number-citation ref-id="documentEnd"/>
                      </fo:inline>
                    </fo:block>
                  </fo:table-cell>
                  <fo:table-cell >
                    <fo:block text-align="right">
                      <fo:inline font-weight="bold" text-align="right">
                        <xsl:value-of select="CurrentDate"></xsl:value-of>
                      </fo:inline>
                    </fo:block>
                  </fo:table-cell>
                </fo:table-row>
              </fo:table-body>
            </fo:table>&#x00A0;
          </fo:block>
        </fo:static-content>
        <fo:flow flow-name="xsl-region-body">
          <fo:table border-collapse='collapse' font-size='6pt' font-family='Arial'>
            <xsl:apply-templates select='columns'></xsl:apply-templates>
            <xsl:apply-templates select='rows'></xsl:apply-templates>
          </fo:table>
          <fo:block id="documentEnd"/>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </xsl:template>

  <xsl:template match="columns">
    <xsl:for-each select="column">
      <fo:table-column column-width='80%'/>
    </xsl:for-each>
    <fo:table-header font-weight='bold' font-size='8pt' line-height="200%" text-align="center" border-top-width="0.5pt" border-top-style="solid" border-top-color="rgb(0,0,0)" border-bottom-width="0.5pt" border-bottom-style="solid" border-bottom-color="rgb(0,0,0)">
      <fo:table-row>
        <xsl:for-each select="column">
          <fo:table-cell padding='2pt'>
            <fo:block text-align='center'>
              <xsl:value-of select='@colName'/>
            </fo:block>
          </fo:table-cell>
        </xsl:for-each>
      </fo:table-row>
    </fo:table-header>
  </xsl:template>

</xsl:stylesheet>

在这里,我们使用XDOC创建了一个XML文档,并使用XSLT将此XML转换为另一个XML,请按照以下代码进行操作:

    string[] ReportTableHeader = { "Headerone", "HeaderTwo", "HeaderTwo"};


XDocument xdoc = new XDocument(new XElement("ReportTable",
                        new XElement("Node1", headerText1),
                        new XElement("Node2", headerText2),
                        new XElement("Node3",headerText3),
                        new XElement("Node4",headerText4),
                        new XElement("CurrentDate", footerCurDate),
                        new XElement("Columns", from col in ReportTableHeader
                                                              select
                                                                  new XElement("Column", new XAttribute("ColName", col.ToString().Trim())))));
XDocument finalXDoc = new XDocument();
                    using (XmlWriter inputStreamXSLT = finalXDoc.CreateWriter())
                    {
                        XslCompiledTransform objXSLT = new XslCompiledTransform();
                        string xsltFilePath = Server.MapPath(BasePage.GetReportPath(formName));
                        objXSLT.Load(xsltFilePath);
                        objXSLT.Transform(xdoc.CreateReader(), inputStreamXSLT);
                    }
                    string inputXMLtoXSLT = finalXDoc.ToString();

这里的finalDoc是稍后生成的XML文档,所以我们使用finalDoc.CreateWriter()方法,xDoc是我们正在读取的xml文件,所以我们使用xdoc.CreateReader()方法,并且我们使用Server.MapPath()方法提供xslt文件的路径。


0

这只是序列化、反序列化和修改对象。

我会生成带有 XSD 的 XML 的 C# 类,然后创建一个方法将每个项目转换为另一种类型。然后您可以反序列化输入的 XML,使用新方法,然后序列化新对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接