使用XPath解析XML(Collada / Dae)文件

8观察者8

我想将我的示例从Qt C ++重写为Python。

输入文件(“ Plane.dae”)

<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <asset>
    <contributor>
      <author>Blender User</author>
      <authoring_tool>Blender 2.83.3 commit date:2020-07-22, commit time:06:01, hash:353e5bd7493e</authoring_tool>
    </contributor>
    <created>2020-08-03T14:03:19</created>
    <modified>2020-08-03T14:03:19</modified>
    <unit name="meter" meter="1"/>
    <up_axis>Z_UP</up_axis>
  </asset>
  <library_effects>
    <effect id="PlaneMaterial-effect">
      <profile_COMMON>
        <technique sid="common">
          <lambert>
            <emission>
              <color sid="emission">0 0 0 1</color>
            </emission>
            <diffuse>
              <color sid="diffuse">0.01664001 0.8000001 0.01191879 1</color>
            </diffuse>
            <reflectivity>
              <float sid="specular">0.5</float>
            </reflectivity>
          </lambert>
        </technique>
      </profile_COMMON>
    </effect>
  </library_effects>
  <library_images/>
  <library_materials>
    <material id="PlaneMaterial-material" name="PlaneMaterial">
      <instance_effect url="#PlaneMaterial-effect"/>
    </material>
  </library_materials>
  <library_geometries>
    <geometry id="Plane-mesh" name="Plane">
      <mesh>
        <source id="Plane-mesh-positions">
          <float_array id="Plane-mesh-positions-array" count="12">-1 -1 0 1 -1 0 -1 1 0 1 1 0</float_array>
          <technique_common>
            <accessor source="#Plane-mesh-positions-array" count="4" stride="3">
              <param name="X" type="float"/>
              <param name="Y" type="float"/>
              <param name="Z" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <source id="Plane-mesh-normals">
          <float_array id="Plane-mesh-normals-array" count="3">0 0 1</float_array>
          <technique_common>
            <accessor source="#Plane-mesh-normals-array" count="1" stride="3">
              <param name="X" type="float"/>
              <param name="Y" type="float"/>
              <param name="Z" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <source id="Plane-mesh-map-0">
          <float_array id="Plane-mesh-map-0-array" count="12">1 0 0 1 0 0 1 0 1 1 0 1</float_array>
          <technique_common>
            <accessor source="#Plane-mesh-map-0-array" count="6" stride="2">
              <param name="S" type="float"/>
              <param name="T" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <vertices id="Plane-mesh-vertices">
          <input semantic="POSITION" source="#Plane-mesh-positions"/>
        </vertices>
        <triangles material="PlaneMaterial-material" count="2">
          <input semantic="VERTEX" source="#Plane-mesh-vertices" offset="0"/>
          <input semantic="NORMAL" source="#Plane-mesh-normals" offset="1"/>
          <input semantic="TEXCOORD" source="#Plane-mesh-map-0" offset="2" set="0"/>
          <p>1 0 0 2 0 1 0 0 2 1 0 3 3 0 4 2 0 5</p>
        </triangles>
      </mesh>
    </geometry>
  </library_geometries>
  <library_visual_scenes>
    <visual_scene id="Scene" name="Scene">
      <node id="Plane" name="Plane" type="NODE">
        <matrix sid="transform">1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</matrix>
        <instance_geometry url="#Plane-mesh" name="Plane">
          <bind_material>
            <technique_common>
              <instance_material symbol="PlaneMaterial-material" target="#PlaneMaterial-material">
                <bind_vertex_input semantic="UVMap" input_semantic="TEXCOORD" input_set="0"/>
              </instance_material>
            </technique_common>
          </bind_material>
        </instance_geometry>
      </node>
    </visual_scene>
  </library_visual_scenes>
  <scene>
    <instance_visual_scene url="#Scene"/>
  </scene>
</COLLADA>

Qt C ++:

    QString planePath = ":/Models/Plane.dae";
    QFile f(planePath);
    if (!f.open(QIODevice::ReadOnly))
    {
        std::cerr << "Failed to load the file: " <<
                     planePath.toStdString() << std::endl;
        return;
    }
 
    QXmlQuery query;
    query.bindVariable("myFile", &f);
//    query.setQuery("doc($myFile)//*[local-name() = 'p']/text()"); // it works too but it is XPath 1.0
    query.setQuery("doc($myFile)//*:p/text()");
 
    QString result;
    query.evaluateTo(&result);
    qDebug() << result;
    f.close();

我尝试用Python重写,但我的示例在下一行冻结:

        query.setQuery("doc($myFile)//*:p/text()")
        # query.setQuery("doc($myFile)//*[local-name() = 'p']/text()")

main.py


import sys
from PySide2.QtCore import QFile, QIODevice
from PySide2.QtXmlPatterns import QXmlQuery, QXmlResultItems
from PySide2.QtWidgets import (QApplication,
    QTextEdit, QWidget)

class Window(QWidget):

    def __init__(self):
        super().__init__()
        self.resize(250, 250)
        output = QTextEdit("", self)
        planePath = "./Plane.dae"
        f = QFile(planePath)
        if not f.open(QIODevice.ReadOnly):
            print("Falied to load the file:", planePath)
        query = QXmlQuery()
        query.bindVariable("myFile", f)
        query.setQuery("doc($myFile)//*:p/text()")
        # query.setQuery("doc($myFile)//*[local-name() = 'p']/text()")
        result = QXmlResultItems()
        query.evaluateTo(result)
        output.setText("Hello")

def main():
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
永乐

看来这是一个PySide2错误,如果我们使用gdb调试代码,则会获得以下信息:

(qt_venv) [qt_user@machine ~]$ gdb --args python main.py
GNU gdb (GDB) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from python...
(No debugging symbols found in python)
(gdb) run
Starting program: /home/qt_user/Documents/qt_venv/bin/python main.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[New Thread 0x7ffff3e8f700 (LWP 27932)]
[New Thread 0x7ffff168e700 (LWP 27933)]
[New Thread 0x7fffeee8d700 (LWP 27934)]
[New Thread 0x7fffe2106700 (LWP 27935)]
[New Thread 0x7fffe149f700 (LWP 27936)]
[New Thread 0x7fffe0a67700 (LWP 27937)]

Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007fffe5ba1b0c in QPatternist::TypeChecker::verifyType(QExplicitlySharedDataPointer<QPatternist::Expression> const&, QExplicitlySharedDataPointer<QPatternist::SequenceType const> const&, QExplicitlySharedDataPointer<QPatternist::StaticContext> const&, QPatternist::ReportContext::ErrorCode, QFlags<QPatternist::TypeChecker::Option>) () from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
(gdb) backtrace
#0  0x00007fffe5ba1b0c in QPatternist::TypeChecker::verifyType(QExplicitlySharedDataPointer<QPatternist::Expression> const&, QExplicitlySharedDataPointer<QPatternist::SequenceType const> const&, QExplicitlySharedDataPointer<QPatternist::StaticContext> const&, QPatternist::ReportContext::ErrorCode, QFlags<QPatternist::TypeChecker::Option>) () from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
#1  0x00007fffe5ba38da in QPatternist::TypeChecker::applyFunctionConversion(QExplicitlySharedDataPointer<QPatternist::Expression> const&, QExplicitlySharedDataPointer<QPatternist::SequenceType const> const&, QExplicitlySharedDataPointer<QPatternist::StaticContext> const&, QPatternist::ReportContext::ErrorCode, QFlags<QPatternist::TypeChecker::Option>) () from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
#2  0x00007fffe5a71f41 in QPatternist::resolveVariable(QXmlName const&, YYLTYPE const&, QPatternist::ParserContext*, bool) ()
   from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
#3  0x00007fffe5a78616 in QPatternist::XPathparse(QPatternist::ParserContext*) ()
   from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
#4  0x00007fffe59cb98f in QPatternist::ExpressionFactory::createExpression(QExplicitlySharedDataPointer<QPatternist::Tokenizer> const&, QExplicitlySharedDataPointer<QPatternist::StaticContext> const&, QXmlQuery::QueryLanguage, QExplicitlySharedDataPointer<QPatternist::SequenceType const> const&, QUrl const&, QXmlName const&) ()
   from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
#5  0x00007fffe59cd983 in QPatternist::ExpressionFactory::createExpression(QIODevice*, QExplicitlySharedDataPointer<QPatternist::StaticContext> const&, QXmlQuery::QueryLanguage, QExplicitlySharedDataPointer<QPatternist::SequenceType const> const&, QUrl const&, QXmlName const&) ()
   from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
#6  0x00007fffe597be6c in QXmlQuery::setQuery(QIODevice*, QUrl const&) ()
   from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
#7  0x00007fffe597cba8 in QXmlQuery::setQuery(QString const&, QUrl const&) ()
   from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/Qt/lib/libQt5XmlPatterns.so.5
#8  0x00007fffe5eb1ce8 in Sbk_QXmlQueryFunc_setQuery () from /home/qt_user/Documents/qt_venv/lib/python3.8/site-packages/PySide2/QtXmlPatterns.abi3.so
#9  0x00007ffff7b3dee5 in ?? () from /usr/lib/libpython3.8.so.1.0
#10 0x00007ffff7b2bb41 in _PyEval_EvalFrameDefault () from /usr/lib/libpython3.8.so.1.0
#11 0x00007ffff7b2a5ba in _PyEval_EvalCodeWithName () from /usr/lib/libpython3.8.so.1.0
#12 0x00007ffff7b3428e in _PyObject_FastCallDict () from /usr/lib/libpython3.8.so.1.0
#13 0x00007ffff7b46d64 in ?? () from /usr/lib/libpython3.8.so.1.0
#14 0x00007ffff7b34c90 in _PyObject_MakeTpCall () from /usr/lib/libpython3.8.so.1.0
#15 0x00007ffff7b2ffc4 in _PyEval_EvalFrameDefault () from /usr/lib/libpython3.8.so.1.0
#16 0x00007ffff7b3c138 in _PyFunction_Vectorcall () from /usr/lib/libpython3.8.so.1.0
#17 0x00007ffff7b2b77c in _PyEval_EvalFrameDefault () from /usr/lib/libpython3.8.so.1.0
#18 0x00007ffff7b2a0c4 in _PyEval_EvalCodeWithName () from /usr/lib/libpython3.8.so.1.0
#19 0x00007ffff7bdb323 in PyEval_EvalCode () from /usr/lib/libpython3.8.so.1.0
#20 0x00007ffff7be6b98 in ?? () from /usr/lib/libpython3.8.so.1.0
#21 0x00007ffff7be0db3 in ?? () from /usr/lib/libpython3.8.so.1.0
#22 0x00007ffff7a9fa0b in PyRun_FileExFlags () from /usr/lib/libpython3.8.so.1.0
#23 0x00007ffff7a9f482 in PyRun_SimpleFileExFlags () from /usr/lib/libpython3.8.so.1.0
#24 0x00007ffff7bf3a1a in Py_RunMain () from /usr/lib/libpython3.8.so.1.0
#25 0x00007ffff7bcfbd9 in Py_BytesMain () from /usr/lib/libpython3.8.so.1.0
#26 0x00007ffff7dc3002 in __libc_start_main () from /usr/lib/libc.so.6
#27 0x000055555555504e in _start ()

可以观察到试图访问一个对象,但尚未保留其内存。我的建议是您报告它,并且可能在下一版本中将其解决。

因此,正如您的问题指向在python中使用代码一样,一种选择是使用PyQt5:

import sys
from PyQt5.QtCore import QBuffer, QByteArray, QFile, QIODevice, QTextCodec
from PyQt5.QtXmlPatterns import QXmlQuery
from PyQt5.QtWidgets import QApplication, QTextEdit, QVBoxLayout, QWidget


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(250, 250)
        output = QTextEdit()
        lay = QVBoxLayout(self)
        lay.addWidget(output)

        planePath = "./Plane.dae"
        f = QFile(planePath)
        if not f.open(QIODevice.ReadOnly):
            print("Falied to load the file:", planePath)
        query = QXmlQuery()
        query.bindVariable("myFile", f)
        query.setQuery("doc($myFile)//*:p/text()")

        ba = QByteArray()
        buf = QBuffer(ba)
        buf.open(QIODevice.ReadWrite)

        query.evaluateTo(buf)

        text = QTextCodec.codecForName("UTF-8").toUnicode(ba)
        output.setText(text)


def main():
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章