读取大 xml 文件

如何解决读取大 xml 文件

我需要在 Microsoft Visual FoxPro 9 SP2 桌面应用程序中读取大 xml 文件。 创建包含所需列和 convert.xsl 文件的游标结果,以将 xml 转换为 xmltocursor 可读的格式。

尝试过

source = CreateObject('MSXML.Domdocument')
stylesheet = CreateObject('MSXML.Domdocument')
resultDoc = CreateObject('MSXML.Domdocument')
resultDoc.validateOnParse = .t.
stylesheet.load('convert.xsl')
source.load( 'bigxml.xml' )
source.transformNodetoObject(stylesheet,@resultDoc)

* Exception code=E06D7363
IF XMLToCursor(resultDoc.xml,'result',8192 )=0

但是得到了

Fatal exception 

Exception code=E06D7363 

在线

IF XMLToCursor(resultDoc.xml,8192 )=0

应用程序终止。

如何将大的 xml 文件转换为光标?

XSL 是:

<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="yes"/>

  <!-- this replaces root tag with VFPData which is required from CursorToXML to work properly -->
  <xsl:template match="/">
    <xsl:element name="VFPData">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <!-- this will denormalize XML data -->
  <xsl:template match="/ettevotjad/ettevotja">

    <xsl:element name="Document-Ariregister">

      <xsl:element name="nimi">
        <xsl:value-of select="nimi"/>
      </xsl:element>

      <xsl:element name="ariregistr">
        <xsl:value-of select="ariregistri_kood"/>
      </xsl:element>

      <xsl:element name="kmkr_nr">
        <xsl:value-of select="kmkr_nr"/>
      </xsl:element>

      <xsl:element name="ettevotja_">
        <xsl:value-of select="ettevotja_staatus"/>
      </xsl:element>

      <xsl:element name="asukoht_et">
        <xsl:value-of select="ettevotja_aadress/asukoht_ettevotja_aadressis"/>
      </xsl:element>

      <xsl:element name="asukoha_e2">
        <xsl:value-of select="ettevotja_aadress/asukoha_ehak_tekstina"/>
      </xsl:element>

      <xsl:element name="indeks_ett">
        <xsl:value-of select="ettevotja_aadress/indeks_ettevotja_aadressis"/>
      </xsl:element>
  
    </xsl:element>
  </xsl:template>

  <!-- to ommit nodes data -->
  <xsl:template match="text()">
  </xsl:template>

  <!-- to work over every node -->
  <xsl:template match="*">
    <xsl:apply-templates/>
  </xsl:template>

</xsl:stylesheet>

解决方法

这里是使用mxml.6.0的解决方案,不需要xs文件:

* requires msxml.6.0! ( https://www.microsoft.com/es-es/download/details.aspx?id=3988 )
*
Parameters fileName,xPath

fileName = "D:\Data\Xml\ettevotja_rekvisiidid_2021-01-27.xml"
xPath = '/ettevotjad'

xPath = RTRIM(m.xPath,1,'/')

Private All

    oxml = Createobject('msxml2.domDocument.6.0')

    Wait 'loading document...' Window Nowait

    With oXml As msxml.DOMDocument
        .Load(Fullpath(m.fileName))
        Wait Clear
        If .parseError.errorCode # 0
            Messagebox(.parseError.reason,16)
            Return
        Endif
    Endwith


Close Tables All

nsteps = 500
tini = Seconds()
Set Escape On

x =  1

DO WHILE .t.

    subset = oXml.selectNodes(Textmerge(m.xPath+'/*[ position() >= <<m.x>> and position() < <<m.x+m.nsteps>> ]'))

    IF subset.length = 0
        EXIT
    ENDIF

    cXml = ''

    For Y = 1 To subset.Length
        m.cXml = m.cXml + subset.Item(m.y-1).XML
    ENDFOR
    
    x = m.x + subset.Length

    Wait Textmerge('<<m.x-1>> records  << (m.x-1) / (SECONDS() - m.tini) >> records/sec ') Window nowait
    
    cXml = '<xml encoding="windows-1252">'+m.cXml+'</xml>'

    Xmltocursor(m.cXml,'xmlImport',Iif(Used('xmlImport'),4+8192,0))


ENDDO



Browse Normal Font 'consolas,8'



,

我喜欢 Marco 的解决方案,至少它在 VFP 中。但是,拥有像这样的大型 XML 文件,我也会关心性能。我尝试使用 Marco 的代码,它花了 80 多秒才能完成,如果您真的希望像在 XSL 中那样将这些字段分开,则可能需要做一些工作。

我尝试过,从那个 XML 中读取,根据您的 XSL 进行转换并使用 C# 写入 SQLite 数据库。花了 7.2 秒,这些地址线已经分开了。 如果您无论如何都要使用,这里是 C# 代码:

void Main()
{
    string dataFile = @"d:\Andrus\bigdata.sqlite";
    string constr = $"Data Source={dataFile}";

    Stopwatch sw = new Stopwatch();
    sw.Start();

    if (!File.Exists(dataFile))
    {
        CreateDatabase(constr);
    }

    InsertData(constr,@"d:\Andrus\bigxml.xml");

    sw.Stop();
    sw.Dump("Duration");

}

void InsertData(string connectionString,string xmlFile)
{
    using (SQLiteConnection conn = new SQLiteConnection(connectionString))
    using (SQLiteCommand sql = new SQLiteCommand(@"insert into MyData 
        (nimi,ariregistr,asukoht_et,asukoha_e2,indeks_ett,kmkr_nr)
        values
        (?,?,?)",conn))
    {
        sql.Parameters.AddWithValue("nimi","");
        sql.Parameters.AddWithValue("ariregistr",0);
        sql.Parameters.AddWithValue("asukoht_et","");
        sql.Parameters.AddWithValue("asukoha_e2","");
        sql.Parameters.AddWithValue("indeks_ett","");
        sql.Parameters.AddWithValue("kmkr_nr","");

        conn.Open();
        SQLiteTransaction transaction = conn.BeginTransaction();

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.IgnoreWhitespace = true;
        using (XmlReader r = XmlReader.Create(xmlFile,settings))
        {
            r.MoveToContent();
            r.ReadStartElement("ettevotjad");
            while (r.Name == "ettevotja")
            {
                XElement x = (XElement)XNode.ReadFrom(r);

                string nimi = (string)x.Element("nimi");
                int? ariregistr = (int?)x.Element("ariregistri_kood");
                string asukoht_et = (string)x.Element("ettevotja_aadress").Element("asukoht_ettevotja_aadressis");
                string asukoha_e2 = (string)x.Element("ettevotja_aadress").Element("asukoha_ehak_tekstina");
                string indeks_ett = (string)x.Element("ettevotja_aadress").Element("indeks_ettevotja_aadressis");
                string kmkr_nr = (string)x.Element("kmkr_nr");

                ///
                sql.Parameters["nimi"].Value = nimi;
                sql.Parameters["ariregistr"].Value = ariregistr;
                sql.Parameters["asukoht_et"].Value = asukoht_et;
                sql.Parameters["asukoha_e2"].Value = asukoha_e2;
                sql.Parameters["indeks_ett"].Value = indeks_ett;
                sql.Parameters["kmkr_nr"].Value = kmkr_nr;

                sql.ExecuteNonQuery();
            }
            r.ReadEndElement();
        }
        transaction.Commit();
        conn.Close();
    }
}

void CreateDatabase(string connectionString)
{
    using (SQLiteConnection conn = new SQLiteConnection(connectionString))
    using (SQLiteCommand sql = new SQLiteCommand())
    {
        sql.CommandText = @"create table MyData (
            nimi text,ariregistr number null,asukoht_et text,asukoha_e2 text,indeks_ett text,kmkr_nr text
            )";
        sql.Connection = conn;

        conn.Open();
        sql.ExecuteNonQuery();
        conn.Close();
    }
}

PS:代码直接在 LinqPad 中运行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?