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

时间:2013-11-19 18:31:20

标签: c# xml xml-parsing

我有一个非常大的xml文件,其中包含一些我感兴趣的信息,但我需要以另一种方式呈现它。让我来说明一下:

SOURCE 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#中实现这一目标?

4 个答案:

答案 0 :(得分:3)

您可以尝试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#

希望它有所帮助。

答案 1 :(得分: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);
            }
}

答案 2 :(得分:0)

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

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

答案 3 :(得分: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 Doc,所以我们使用finalDoc.CreateWriter()方法,而xDoc是我们正在读取的xml,所以我们使用xdoc.CreateReader()方法,我们提供了使用Server.MapPath()方法的xslt文件。