一生一世学坛

 找回密码
 立即注册
搜索
查看: 5135|回复: 0
打印 上一主题 下一主题

Qt 解析xml并高亮显示模式校验错误部分

[复制链接]

334

主题

385

帖子

6816

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
6816
跳转到指定楼层
楼主
发表于 2022-7-1 16:56:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #ifndef XMLSYNTAXHIGHLIGHTER_H
  2. #define XMLSYNTAXHIGHLIGHTER_H

  3. #include <QtCore/QRegExp>
  4. #include <QtGui/QSyntaxHighlighter>

  5. class XmlSyntaxHighlighter : public QSyntaxHighlighter
  6. {
  7.     public:
  8.         explicit XmlSyntaxHighlighter(QTextDocument *parent = nullptr);

  9.     protected:
  10.         virtual void highlightBlock(const QString &text);

  11.     private:
  12.         struct HighlightingRule
  13.         {
  14.             QRegExp pattern;
  15.             QTextCharFormat format;
  16.         };
  17.         QVector<HighlightingRule> highlightingRules;

  18.         QRegExp commentStartExpression;
  19.         QRegExp commentEndExpression;

  20.         QTextCharFormat tagFormat;
  21.         QTextCharFormat attributeFormat;
  22.         QTextCharFormat attributeContentFormat;
  23.         QTextCharFormat commentFormat;
  24. };

  25. #endif
  26. #ifndef MAINWINDOW_H
  27. #define MAINWINDOW_H

  28. #include <QMainWindow>

  29. #include "ui_schema.h"

  30. //! [0]
  31. class MainWindow : public QMainWindow,
  32.                    private Ui::SchemaMainWindow
  33. {
  34.     Q_OBJECT

  35. public:
  36.     MainWindow();

  37. private Q_SLOTS:
  38.     void schemaSelected(int index);
  39.     void instanceSelected(int index);
  40.     void validate();
  41.     void textChanged();

  42. private:
  43.     void moveCursor(int line, int column);
  44. };
  45. //! [0]
  46. #endif
  47. #include "xmlsyntaxhighlighter.h"

  48. XmlSyntaxHighlighter::XmlSyntaxHighlighter(QTextDocument *parent)
  49.     : QSyntaxHighlighter(parent)
  50. {
  51.     HighlightingRule rule;

  52.     // tag format
  53.     tagFormat.setForeground(Qt::darkBlue);
  54.     tagFormat.setFontWeight(QFont::Bold);
  55.     rule.pattern = QRegExp("(<[a-zA-Z:]+\\b|<\\?[a-zA-Z:]+\\b|\\?>|>|/>|</[a-zA-Z:]+>)");
  56.     rule.format = tagFormat;
  57.     highlightingRules.append(rule);

  58.     // attribute format
  59.     attributeFormat.setForeground(Qt::darkGreen);
  60.     rule.pattern = QRegExp("[a-zA-Z:]+=");
  61.     rule.format = attributeFormat;
  62.     highlightingRules.append(rule);

  63.     // attribute content format
  64.     attributeContentFormat.setForeground(Qt::red);
  65.     rule.pattern = QRegExp("("[^"]*"|'[^']*')");
  66.     rule.format = attributeContentFormat;
  67.     highlightingRules.append(rule);

  68.     commentFormat.setForeground(Qt::lightGray);
  69.     commentFormat.setFontItalic(true);

  70.     commentStartExpression = QRegExp("<!--");
  71.     commentEndExpression = QRegExp("-->");
  72. }

  73. void XmlSyntaxHighlighter::highlightBlock(const QString &text)
  74. {
  75.      for (const HighlightingRule &rule : qAsConst(highlightingRules)) {
  76.          QRegExp expression(rule.pattern);
  77.          int index = text.indexOf(expression);
  78.          while (index >= 0) {
  79.              int length = expression.matchedLength();
  80.              setFormat(index, length, rule.format);
  81.              index = text.indexOf(expression, index + length);
  82.          }
  83.      }
  84.      setCurrentBlockState(0);

  85.      int startIndex = 0;
  86.      if (previousBlockState() != 1)
  87.          startIndex = text.indexOf(commentStartExpression);

  88.      while (startIndex >= 0) {
  89.          int endIndex = text.indexOf(commentEndExpression, startIndex);
  90.          int commentLength;
  91.          if (endIndex == -1) {
  92.              setCurrentBlockState(1);
  93.              commentLength = text.length() - startIndex;
  94.          } else {
  95.              commentLength = endIndex - startIndex
  96.                              + commentEndExpression.matchedLength();
  97.          }
  98.          setFormat(startIndex, commentLength, commentFormat);
  99.          startIndex = text.indexOf(commentStartExpression,
  100.                                                  startIndex + commentLength);
  101.      }
  102. }

  103. #include <QtGui>
  104. #include <QtXmlPatterns>

  105. #include "mainwindow.h"
  106. #include "xmlsyntaxhighlighter.h"

  107. //! [4]
  108. class MessageHandler : public QAbstractMessageHandler
  109. {
  110. public:
  111.     MessageHandler()
  112.         : QAbstractMessageHandler(0)
  113.     {
  114.     }

  115.     QString statusMessage() const
  116.     {
  117.         return m_description;
  118.     }

  119.     int line() const
  120.     {
  121.         return m_sourceLocation.line();
  122.     }

  123.     int column() const
  124.     {
  125.         return m_sourceLocation.column();
  126.     }

  127. protected:
  128.     virtual void handleMessage(QtMsgType type, const QString &description,
  129.                                const QUrl &identifier, const QSourceLocation &sourceLocation)
  130.     {
  131.         Q_UNUSED(type);
  132.         Q_UNUSED(identifier);

  133.         m_description = description;
  134.         m_sourceLocation = sourceLocation;
  135.     }

  136. private:
  137.     QString m_description;
  138.     QSourceLocation m_sourceLocation;
  139. };
  140. //! [4]

  141. //! [0]
  142. MainWindow::MainWindow()
  143. {
  144.     setupUi(this);

  145.     new XmlSyntaxHighlighter(schemaView->document());
  146.     new XmlSyntaxHighlighter(instanceEdit->document());

  147.     schemaSelection->addItem(tr("Contact Schema"));
  148.     schemaSelection->addItem(tr("Recipe Schema"));
  149.     schemaSelection->addItem(tr("Order Schema"));

  150.     instanceSelection->addItem(tr("Valid Contact Instance"));
  151.     instanceSelection->addItem(tr("Invalid Contact Instance"));

  152.     connect(schemaSelection, SIGNAL(currentIndexChanged(int)), SLOT(schemaSelected(int)));
  153.     connect(instanceSelection, SIGNAL(currentIndexChanged(int)), SLOT(instanceSelected(int)));
  154.     connect(validateButton, SIGNAL(clicked()), SLOT(validate()));
  155.     connect(instanceEdit, SIGNAL(textChanged()), SLOT(textChanged()));

  156.     validationStatus->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);

  157.     schemaSelected(0);
  158.     instanceSelected(0);
  159. }
  160. //! [0]

  161. //! [1]
  162. void MainWindow::schemaSelected(int index)
  163. {
  164.     instanceSelection->clear();
  165.     if (index == 0) {
  166.         instanceSelection->addItem(tr("Valid Contact Instance"));
  167.         instanceSelection->addItem(tr("Invalid Contact Instance"));
  168.     } else if (index == 1) {
  169.         instanceSelection->addItem(tr("Valid Recipe Instance"));
  170.         instanceSelection->addItem(tr("Invalid Recipe Instance"));
  171.     } else if (index == 2) {
  172.         instanceSelection->addItem(tr("Valid Order Instance"));
  173.         instanceSelection->addItem(tr("Invalid Order Instance"));
  174.     }
  175.     textChanged();

  176.     const QString fileName = QStringLiteral(":/schema_")
  177.         + QString::number(index) + QStringLiteral(".xsd");
  178.     QFile schemaFile(fileName);
  179.     if (!schemaFile.open(QIODevice::ReadOnly)) {
  180.         qWarning() << "Cannot open" << QDir::toNativeSeparators(fileName)
  181.             << ':' << schemaFile.errorString();
  182.         return;
  183.     }

  184.     const QString schemaText(QString::fromUtf8(schemaFile.readAll()));
  185.     schemaView->setPlainText(schemaText);

  186.     validate();
  187. }
  188. //! [1]

  189. //! [2]
  190. void MainWindow::instanceSelected(int index)
  191. {
  192.     if (index < 0) {
  193.         instanceEdit->setPlainText(QString());
  194.         return;
  195.     }
  196.     const QString fileName = QStringLiteral(":/instance_")
  197.         + QString::number(2 * schemaSelection->currentIndex() + index)
  198.         + QStringLiteral(".xml");
  199.     QFile instanceFile(fileName);
  200.     if (!instanceFile.open(QIODevice::ReadOnly)) {
  201.         qWarning() << "Cannot open" << QDir::toNativeSeparators(fileName)
  202.             << ':' << instanceFile.errorString();
  203.         return;
  204.     }
  205.     const QString instanceText(QString::fromUtf8(instanceFile.readAll()));
  206.     instanceEdit->setPlainText(instanceText);

  207.     validate();
  208. }
  209. //! [2]

  210. //! [3]
  211. void MainWindow::validate()
  212. {
  213.     const QByteArray schemaData = schemaView->toPlainText().toUtf8();
  214.     const QByteArray instanceData = instanceEdit->toPlainText().toUtf8();

  215.     MessageHandler messageHandler;

  216.     QXmlSchema schema;
  217.     schema.setMessageHandler(&messageHandler);

  218.     schema.load(schemaData);

  219.     bool errorOccurred = false;
  220.     if (!schema.isValid()) {
  221.         errorOccurred = true;
  222.     } else {
  223.         QXmlSchemaValidator validator(schema);
  224.         if (!validator.validate(instanceData))
  225.             errorOccurred = true;
  226.     }

  227.     if (errorOccurred) {
  228.         validationStatus->setText(messageHandler.statusMessage());
  229.         moveCursor(messageHandler.line(), messageHandler.column());
  230.     } else {
  231.         validationStatus->setText(tr("validation successful"));
  232.     }

  233.     const QString styleSheet = QString("QLabel {background: %1; padding: 3px}")
  234.                                       .arg(errorOccurred ? QColor(Qt::red).lighter(160).name() :
  235.                                                            QColor(Qt::green).lighter(160).name());
  236.     validationStatus->setStyleSheet(styleSheet);
  237. }
  238. //! [3]

  239. void MainWindow::textChanged()
  240. {
  241.     instanceEdit->setExtraSelections(QList<QTextEdit::ExtraSelection>());
  242. }

  243. void MainWindow::moveCursor(int line, int column)
  244. {
  245.     instanceEdit->moveCursor(QTextCursor::Start);
  246.     for (int i = 1; i < line; ++i)
  247.         instanceEdit->moveCursor(QTextCursor::Down);

  248.     for (int i = 1; i < column; ++i)
  249.         instanceEdit->moveCursor(QTextCursor::Right);

  250.     QList<QTextEdit::ExtraSelection> extraSelections;
  251.     QTextEdit::ExtraSelection selection;

  252.     const QColor lineColor = QColor(Qt::red).lighter(160);
  253.     selection.format.setBackground(lineColor);
  254.     selection.format.setProperty(QTextFormat::FullWidthSelection, true);
  255.     selection.cursor = instanceEdit->textCursor();
  256.     selection.cursor.clearSelection();
  257.     extraSelections.append(selection);

  258.     instanceEdit->setExtraSelections(extraSelections);

  259.     instanceEdit->setFocus();
  260. }
  261. #include <QtGui>
  262. #include "mainwindow.h"

  263. //! [0]
  264. int main(int argc, char* argv[])
  265. {
  266.     Q_INIT_RESOURCE(schema);
  267.     QApplication app(argc, argv);
  268.     MainWindow* const window = new MainWindow;
  269.     window->show();
  270.     return app.exec();
  271. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|分享学习  

GMT+8, 2024-5-2 14:24 , Processed in 0.063240 second(s), 5 queries , File On.

声明:本站严禁任何人以任何形式发表违法言论!

本站内容由网友原创或转载,如果侵犯了您的合法权益,请及时联系处理!© 2017 zamxqun@163.com

皖公网安备 34010402700634号

皖ICP备17017002号-1

快速回复 返回顶部 返回列表