Преобразуйте XML, используя XSLT, вызывая функцию в c# - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть xml, который необходимо преобразовать в другой формат xml с использованием XSLT и c#.

Мой ввод XML - это что-то в формате ниже

  <Root>
  <Table>
    <TR>
      <TH>Column1</TH>
      <TH>Column2</TH>
    </TR>
    <TR>
      <TD>ABC</TD>
      <TD>DEF</TD>
    </TR>
  </Table>
  <Part>
    <Table>
      <TR>
        <TH>Column1</TH>
        <TH>Column2</TH>
      </TR>
      <TR>
        <TD>GHI</TD>
        <TD>JKL</TD>
      </TR>
      <TR>
        <TD>MNO</TD>
        <TD>PQR</TD>
      </TR>
    </Table>
    <Table>
      <TR>
        <TH>XYZ</TH>
        <TH>Column2</TH>
      </TR>
      <TR>
        <TD>GHI</TD>
        <TD>JKL</TD>
      </TR>
      <TR>
        <TD>MNO</TD>
        <TD>PQR</TD>
      </TR>
    </Table>
    Some unwanted text
  </Part>
  <Part>
    Some unwanted text again
  </Part>
</Root>

Мой вывод XML должен быть в формате ниже, который будет комбинацией таблиц в xml.

<Table>
    <Column1>ABC</Column1>
    <Column2>DEF</Column2>
    <Column1>GHI</Column1>
    <Column2>JKL</Column2>
    <Column1>MNO</Column1>
    <Column2>PQR</Column2>
</Table>

Ниже приведен фрагмент XSLT, который я использую

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:spext="urn:Converter:extensions">
        <xsl:template match="/">
            <xsl:apply-templates select= "/Root"/>
        </xsl:template>
        <xsl:template match="//Table[.//TH[contains(text(), 'Column1')]]">
            <xsl:copy-of select= "spext:Converter(., 'true', './TR[1]', '1')"/>
        </xsl:template>
    </xsl:stylesheet>

Ниже приведен код c#

public string Transform(XmlDocument inputXML, string xsltPath, string outputFile)
{
string result = null;
XslTransform transform = new XslTransform();
XmlDocument stylesheet = new XmlDocument();
stylesheet.Load(xsltPath);
transform.Load(stylesheet);

XsltArgumentList args = new XsltArgumentList();
args.AddExtensionObject("urn:XMLConverter:extensions", new Extensions());
AddExternalExtensions(args, stylesheet, xsltPath);

Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
using (FileStream fs = new FileStream(outputFile, FileMode.Create))
{
    transform.Transform(xml, args, fs);
}
return result;
}

Когда вышеупомянутый метод Transform вызывается, XSLT будет вызывать метод Converter ().

public XPathNodeIterator Converter(XPathNodeIterator navIter, string inputIsTableNode, string 
relativeXpathForStartNode, string numberOfHeaderRows)
{
        string returnStr = null;
        bool inputIsTable = false;
        XPathNodeIterator xPathNodeIterator = null;
        bool.TryParse(inputIsTableNode, out inputIsTable);

        int numberOfHeaderRow = 1;
        int.TryParse(numberOfHeaderRows, out numberOfHeaderRow);

        if (navIter == null)
        {
            return null;
        }
        XDocument xDoc = XDocument.Parse(navIter.Current.OuterXml);
        XDocument xDocOutput = new XDocument();
        if (inputIsTable)
        {
        xDocOutput.Add(new XElement(xDoc.Root.Name));
        //XML Transformation code here.
        xPathNodeIterator = xDocOutput.CreateNavigator().Select("/");
        }
        return xPathNodeIterator
}

Прямо сейчас, используя приведенный выше метод, выведите, что я получаю ниже которого я не ожидал

<Table>
  <Column1>ABC</Column1>
  <Column2>DEF</Column2>
</Table>
<Table>
  <Column1>GHI</Column1>
  <Column2>JKL</Column2>
</Table>Some unwanted text
<Table>
  <Column1>MNO</Column1>
  <Column2>PQR</Column2>
</Table>

Здесь проблема в том, что я получаю несколько тегов root ("Таблица"), которые должны быть только один, и текст (некоторый нежелательный текст) также добавление, которое не должно быть.

Любая помощь будет высоко ценится!

1 Ответ

0 голосов
/ 03 апреля 2020

Следующее xml linq действительно просто:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string INPUT_FILENAME = @"c:\temp\test.xml";
        const string OUTPUT_FILENAME = @"c:\temp\test1.xml";
        static void Main(string[] args)
        {
            XDocument doc1 = XDocument.Load(INPUT_FILENAME);
            string xmlStr = "<Table></Table>";
            XDocument doc2 = XDocument.Parse(xmlStr);
            XElement table2 = doc2.Root;

            foreach (XElement table1 in doc1.Descendants("Table"))
            {
                string[] columnNames = table1.Descendants("TH").Select(x => (string)x).ToArray();

                foreach (XElement tr in table1.Descendants("TR"))
                {
                    List<XElement> rows = tr.Descendants("TD").Select((x, i) => new XElement(columnNames[i], (string)x)).ToList();
                    table2.Add(rows);
                }
            }
            doc2.Save(OUTPUT_FILENAME);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...