1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qdocumentprojector_p.h"
46 using namespace QPatternist;
48 DocumentProjector::DocumentProjector(const ProjectedExpression::Vector &paths,
49 QAbstractXmlReceiver *const receiver) : m_paths(paths)
50 , m_pathCount(paths.count())
51 , m_action(ProjectedExpression::Move)
53 , m_receiver(receiver)
55 Q_ASSERT_X(paths.count() > 0, Q_FUNC_INFO,
56 "Using DocumentProjector with no paths is an "
57 "overhead and has also undefined behavior.");
61 void DocumentProjector::startElement(const QXmlName name)
67 case ProjectedExpression::KeepSubtree:
69 m_receiver->startElement(name);
72 case ProjectedExpression::Skip:
79 Q_ASSERT_X(m_action == ProjectedExpression::Move, Q_FUNC_INFO,
80 "We're not supposed to receive Keep here, because "
81 "endElement() should always end that state.");
83 for(int i = 0; i < m_pathCount; ++i)
85 m_action = m_paths.at(i)->actionForElement(name, m_paths[i]);
89 case ProjectedExpression::Keep:
91 m_action = ProjectedExpression::Keep;
94 case ProjectedExpression::KeepSubtree:
96 /* Ok, at least one path wanted this node. Pass it on,
98 m_receiver->startElement(name);
102 case ProjectedExpression::Skip:
104 /* This particular path doesn't need it, but
105 * some other path might, so continue looping. */
108 case ProjectedExpression::Move:
109 Q_ASSERT_X(false, Q_FUNC_INFO, "The action functions can never return Move.");
115 if(m_action == ProjectedExpression::Keep)
116 m_receiver->startElement(name);
119 Q_ASSERT(m_action == ProjectedExpression::Skip);
125 void DocumentProjector::endElement()
127 if(m_action == ProjectedExpression::Keep)
129 Q_ASSERT(m_nodesInProcess == 1);
131 m_receiver->endElement();
133 /* We have now kept the single node, and now wants to skip
134 * all its children. */
135 m_action = ProjectedExpression::Skip;
136 m_nodesInProcess = 0;
138 else if(m_action == ProjectedExpression::KeepSubtree)
140 m_receiver->endElement();
143 if(m_nodesInProcess == 0)
145 /* We have now skipped all the children, let's do
146 * a new path analysis. */
147 m_action = ProjectedExpression::Move;
152 Q_ASSERT_X(m_action == ProjectedExpression::Skip, Q_FUNC_INFO,
153 "We're not supposed to be in a Move action here.");
154 /* We skip calling m_receiver's endElement() here since we're
156 Q_ASSERT(m_nodesInProcess > 0);
159 if(m_nodesInProcess == 0)
161 /* Ok, we've skipped them all, let's do something
162 * new -- let's Move on to the next path! */
163 m_action = ProjectedExpression::Move;
168 void DocumentProjector::attribute(const QXmlName name,
169 const QString &value)
175 void DocumentProjector::namespaceBinding(const QXmlName nb)
180 void DocumentProjector::comment(const QString &value)
182 Q_ASSERT_X(!value.contains(QLatin1String("--")), Q_FUNC_INFO,
183 "Invalid input; it's the caller's responsibility to ensure the input is correct.");
187 void DocumentProjector::characters(const QString &value)
192 void DocumentProjector::processingInstruction(const QXmlName name,
193 const QString &value)
195 Q_ASSERT_X(!value.contains(QLatin1String("?>")), Q_FUNC_INFO,
196 "Invalid input; it's the caller's responsibility to ensure the input is correct.");
201 void DocumentProjector::item(const Item &outputItem)
203 Q_UNUSED(outputItem);
206 void DocumentProjector::startDocument()
210 void DocumentProjector::endDocument()