【问题标题】:How do I use the information in one xml file to create another in C#?如何使用一个 xml 文件中的信息在 C# 中创建另一个文件?
【发布时间】:2013-11-19 18:31:19
【问题描述】:

我有一个非常大的 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 for XML。有很多可用的例子。您想获取 xdoc.Elements("items") 的所有元素,然后将属性转换为新文档中的元素。

标签: c# xml xml-parsing


【解决方案1】:

您可能想试试XSLT。举几个例子:

Converting XML file to another XML file using XSLT

XML to XML with XSLT omitting specific elements based on value

这是一个关于如何使用 C# 来实现的示例:

How to apply an XSLT Stylesheet in C#

希望对你有帮助。

【讨论】:

  • 我最终选择了这个。我怎么知道 XSLT?!谢谢
  • @Freakishly 总有一些我们不知道的东西,这就是它的乐趣;)
【解决方案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 MasterObject,但我无法掌握 root.Add(_midLevelItem...) 部分。你在哪里调用 MidLevelItemFromXml?
  • 我从我编写的文件中获取了这个。那里的方法都被命名为相同的 ToXmlElement。我在这里进行了更正。
【解决方案3】:

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

我要做的是使用 XSD 生成两个 XML 的 c# 类。然后创建一个将每个项目转换为其他类型的方法。然后您可以反序列化输入 xml,使用您的新方法,然后序列化新对象。

【讨论】:

    【解决方案4】:

    假设我们有一个如下所示的 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 Doc,所以我们使用 finalDoc.CreateWriter() 方法,xDoc 是我们正在读取的 xml,所以我们使用 xdoc.CreateReader() 方法,我们提供了路径xslt 文件使用 Server.MapPath() 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-14
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-02
      相关资源
      最近更新 更多