1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "xfa/fxfa/parser/cxfa_dataexporter.h"
8
9 #include <vector>
10
11 #include "core/fxcrt/fx_basic.h"
12 #include "third_party/base/stl_util.h"
13 #include "xfa/fde/xml/fde_xml_imp.h"
14 #include "xfa/fgas/crt/fgas_codepage.h"
15 #include "xfa/fxfa/parser/cxfa_document.h"
16 #include "xfa/fxfa/parser/cxfa_widgetdata.h"
17 #include "xfa/fxfa/parser/xfa_object.h"
18
19 namespace {
20
ExportEncodeAttribute(const CFX_WideString & str)21 CFX_WideString ExportEncodeAttribute(const CFX_WideString& str) {
22 CFX_WideTextBuf textBuf;
23 int32_t iLen = str.GetLength();
24 for (int32_t i = 0; i < iLen; i++) {
25 switch (str[i]) {
26 case '&':
27 textBuf << L"&";
28 break;
29 case '<':
30 textBuf << L"<";
31 break;
32 case '>':
33 textBuf << L">";
34 break;
35 case '\'':
36 textBuf << L"'";
37 break;
38 case '\"':
39 textBuf << L""";
40 break;
41 default:
42 textBuf.AppendChar(str[i]);
43 }
44 }
45 return textBuf.MakeString();
46 }
47
ExportEncodeContent(const CFX_WideStringC & str)48 CFX_WideString ExportEncodeContent(const CFX_WideStringC& str) {
49 CFX_WideTextBuf textBuf;
50 int32_t iLen = str.GetLength();
51 for (int32_t i = 0; i < iLen; i++) {
52 FX_WCHAR ch = str.GetAt(i);
53 if (!FDE_IsXMLValidChar(ch))
54 continue;
55
56 if (ch == '&') {
57 textBuf << L"&";
58 } else if (ch == '<') {
59 textBuf << L"<";
60 } else if (ch == '>') {
61 textBuf << L">";
62 } else if (ch == '\'') {
63 textBuf << L"'";
64 } else if (ch == '\"') {
65 textBuf << L""";
66 } else if (ch == ' ') {
67 if (i && str.GetAt(i - 1) != ' ') {
68 textBuf.AppendChar(' ');
69 } else {
70 textBuf << L" ";
71 }
72 } else {
73 textBuf.AppendChar(str.GetAt(i));
74 }
75 }
76 return textBuf.MakeString();
77 }
78
SaveAttribute(CXFA_Node * pNode,XFA_ATTRIBUTE eName,const CFX_WideStringC & wsName,bool bProto,CFX_WideString & wsOutput)79 void SaveAttribute(CXFA_Node* pNode,
80 XFA_ATTRIBUTE eName,
81 const CFX_WideStringC& wsName,
82 bool bProto,
83 CFX_WideString& wsOutput) {
84 CFX_WideString wsValue;
85 if ((!bProto && !pNode->HasAttribute((XFA_ATTRIBUTE)eName, bProto)) ||
86 !pNode->GetAttribute((XFA_ATTRIBUTE)eName, wsValue, false)) {
87 return;
88 }
89 wsValue = ExportEncodeAttribute(wsValue);
90 wsOutput += L" ";
91 wsOutput += wsName;
92 wsOutput += L"=\"";
93 wsOutput += wsValue;
94 wsOutput += L"\"";
95 }
96
AttributeSaveInDataModel(CXFA_Node * pNode,XFA_ATTRIBUTE eAttribute)97 bool AttributeSaveInDataModel(CXFA_Node* pNode, XFA_ATTRIBUTE eAttribute) {
98 bool bSaveInDataModel = false;
99 if (pNode->GetElementType() != XFA_Element::Image)
100 return bSaveInDataModel;
101
102 CXFA_Node* pValueNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
103 if (!pValueNode || pValueNode->GetElementType() != XFA_Element::Value)
104 return bSaveInDataModel;
105
106 CXFA_Node* pFieldNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent);
107 if (pFieldNode && pFieldNode->GetBindData() &&
108 eAttribute == XFA_ATTRIBUTE_Href) {
109 bSaveInDataModel = true;
110 }
111 return bSaveInDataModel;
112 }
113
ContentNodeNeedtoExport(CXFA_Node * pContentNode)114 bool ContentNodeNeedtoExport(CXFA_Node* pContentNode) {
115 CFX_WideString wsContent;
116 if (!pContentNode->TryContent(wsContent, false, false))
117 return false;
118
119 ASSERT(pContentNode->IsContentNode());
120 CXFA_Node* pParentNode = pContentNode->GetNodeItem(XFA_NODEITEM_Parent);
121 if (!pParentNode || pParentNode->GetElementType() != XFA_Element::Value)
122 return true;
123
124 CXFA_Node* pGrandParentNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
125 if (!pGrandParentNode || !pGrandParentNode->IsContainerNode())
126 return true;
127 if (pGrandParentNode->GetBindData())
128 return false;
129
130 CXFA_WidgetData* pWidgetData = pGrandParentNode->GetWidgetData();
131 XFA_Element eUIType = pWidgetData->GetUIType();
132 if (eUIType == XFA_Element::PasswordEdit)
133 return false;
134 return true;
135 }
136
RecognizeXFAVersionNumber(CXFA_Node * pTemplateRoot,CFX_WideString & wsVersionNumber)137 void RecognizeXFAVersionNumber(CXFA_Node* pTemplateRoot,
138 CFX_WideString& wsVersionNumber) {
139 wsVersionNumber.clear();
140 if (!pTemplateRoot)
141 return;
142
143 CFX_WideString wsTemplateNS;
144 if (!pTemplateRoot->TryNamespace(wsTemplateNS))
145 return;
146
147 XFA_VERSION eVersion =
148 pTemplateRoot->GetDocument()->RecognizeXFAVersionNumber(wsTemplateNS);
149 if (eVersion == XFA_VERSION_UNKNOWN)
150 eVersion = XFA_VERSION_DEFAULT;
151
152 wsVersionNumber.Format(L"%i.%i", eVersion / 100, eVersion % 100);
153 }
154
RegenerateFormFile_Changed(CXFA_Node * pNode,CFX_WideTextBuf & buf,bool bSaveXML)155 void RegenerateFormFile_Changed(CXFA_Node* pNode,
156 CFX_WideTextBuf& buf,
157 bool bSaveXML) {
158 CFX_WideString wsAttrs;
159 int32_t iAttrs = 0;
160 const uint8_t* pAttrs =
161 XFA_GetElementAttributes(pNode->GetElementType(), iAttrs);
162 while (iAttrs--) {
163 const XFA_ATTRIBUTEINFO* pAttr =
164 XFA_GetAttributeByID((XFA_ATTRIBUTE)pAttrs[iAttrs]);
165 if (pAttr->eName == XFA_ATTRIBUTE_Name ||
166 (AttributeSaveInDataModel(pNode, pAttr->eName) && !bSaveXML)) {
167 continue;
168 }
169 CFX_WideString wsAttr;
170 SaveAttribute(pNode, pAttr->eName, pAttr->pName, bSaveXML, wsAttr);
171 wsAttrs += wsAttr;
172 }
173
174 CFX_WideString wsChildren;
175 switch (pNode->GetObjectType()) {
176 case XFA_ObjectType::ContentNode: {
177 if (!bSaveXML && !ContentNodeNeedtoExport(pNode))
178 break;
179
180 CXFA_Node* pRawValueNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
181 while (pRawValueNode &&
182 pRawValueNode->GetElementType() != XFA_Element::SharpxHTML &&
183 pRawValueNode->GetElementType() != XFA_Element::Sharptext &&
184 pRawValueNode->GetElementType() != XFA_Element::Sharpxml) {
185 pRawValueNode = pRawValueNode->GetNodeItem(XFA_NODEITEM_NextSibling);
186 }
187 if (!pRawValueNode)
188 break;
189
190 CFX_WideString wsContentType;
191 pNode->GetAttribute(XFA_ATTRIBUTE_ContentType, wsContentType, false);
192 if (pRawValueNode->GetElementType() == XFA_Element::SharpxHTML &&
193 wsContentType == L"text/html") {
194 CFDE_XMLNode* pExDataXML = pNode->GetXMLMappingNode();
195 if (!pExDataXML)
196 break;
197
198 CFDE_XMLNode* pRichTextXML =
199 pExDataXML->GetNodeItem(CFDE_XMLNode::FirstChild);
200 if (!pRichTextXML)
201 break;
202
203 CFX_RetainPtr<IFX_MemoryStream> pMemStream =
204 IFX_MemoryStream::Create(true);
205
206 // Note: ambiguous without cast below.
207 CFX_RetainPtr<IFGAS_Stream> pTempStream = IFGAS_Stream::CreateStream(
208 CFX_RetainPtr<IFX_SeekableWriteStream>(pMemStream),
209 FX_STREAMACCESS_Text | FX_STREAMACCESS_Write |
210 FX_STREAMACCESS_Append);
211
212 pTempStream->SetCodePage(FX_CODEPAGE_UTF8);
213 pRichTextXML->SaveXMLNode(pTempStream);
214 wsChildren += CFX_WideString::FromUTF8(
215 CFX_ByteStringC(pMemStream->GetBuffer(), pMemStream->GetSize()));
216 } else if (pRawValueNode->GetElementType() == XFA_Element::Sharpxml &&
217 wsContentType == L"text/xml") {
218 CFX_WideString wsRawValue;
219 pRawValueNode->GetAttribute(XFA_ATTRIBUTE_Value, wsRawValue, false);
220 if (wsRawValue.IsEmpty())
221 break;
222
223 std::vector<CFX_WideString> wsSelTextArray;
224 int32_t iStart = 0;
225 int32_t iEnd = wsRawValue.Find(L'\n', iStart);
226 iEnd = (iEnd == -1) ? wsRawValue.GetLength() : iEnd;
227 while (iEnd >= iStart) {
228 wsSelTextArray.push_back(wsRawValue.Mid(iStart, iEnd - iStart));
229 iStart = iEnd + 1;
230 if (iStart >= wsRawValue.GetLength())
231 break;
232
233 iEnd = wsRawValue.Find(L'\n', iStart);
234 }
235 CXFA_Node* pParentNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
236 ASSERT(pParentNode);
237 CXFA_Node* pGrandparentNode =
238 pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
239 ASSERT(pGrandparentNode);
240 CFX_WideString bodyTagName;
241 bodyTagName = pGrandparentNode->GetCData(XFA_ATTRIBUTE_Name);
242 if (bodyTagName.IsEmpty())
243 bodyTagName = L"ListBox1";
244
245 buf << L"<";
246 buf << bodyTagName;
247 buf << L" xmlns=\"\"\n>";
248 for (int32_t i = 0; i < pdfium::CollectionSize<int32_t>(wsSelTextArray);
249 i++) {
250 buf << L"<value\n>";
251 buf << ExportEncodeContent(wsSelTextArray[i].AsStringC());
252 buf << L"</value\n>";
253 }
254 buf << L"</";
255 buf << bodyTagName;
256 buf << L"\n>";
257 wsChildren += buf.AsStringC();
258 buf.Clear();
259 } else {
260 CFX_WideStringC wsValue = pRawValueNode->GetCData(XFA_ATTRIBUTE_Value);
261 wsChildren += ExportEncodeContent(wsValue);
262 }
263 break;
264 }
265 case XFA_ObjectType::TextNode:
266 case XFA_ObjectType::NodeC:
267 case XFA_ObjectType::NodeV: {
268 CFX_WideStringC wsValue = pNode->GetCData(XFA_ATTRIBUTE_Value);
269 wsChildren += ExportEncodeContent(wsValue);
270 break;
271 }
272 default:
273 if (pNode->GetElementType() == XFA_Element::Items) {
274 CXFA_Node* pTemplateNode = pNode->GetTemplateNode();
275 if (!pTemplateNode ||
276 pTemplateNode->CountChildren(XFA_Element::Unknown) !=
277 pNode->CountChildren(XFA_Element::Unknown)) {
278 bSaveXML = true;
279 }
280 }
281 CFX_WideTextBuf newBuf;
282 CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
283 while (pChildNode) {
284 RegenerateFormFile_Changed(pChildNode, newBuf, bSaveXML);
285 wsChildren += newBuf.AsStringC();
286 newBuf.Clear();
287 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
288 }
289 if (!bSaveXML && !wsChildren.IsEmpty() &&
290 pNode->GetElementType() == XFA_Element::Items) {
291 wsChildren.clear();
292 bSaveXML = true;
293 CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
294 while (pChild) {
295 RegenerateFormFile_Changed(pChild, newBuf, bSaveXML);
296 wsChildren += newBuf.AsStringC();
297 newBuf.Clear();
298 pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling);
299 }
300 }
301 break;
302 }
303
304 if (!wsChildren.IsEmpty() || !wsAttrs.IsEmpty() ||
305 pNode->HasAttribute(XFA_ATTRIBUTE_Name)) {
306 CFX_WideStringC wsElement = pNode->GetClassName();
307 CFX_WideString wsName;
308 SaveAttribute(pNode, XFA_ATTRIBUTE_Name, L"name", true, wsName);
309 buf << L"<";
310 buf << wsElement;
311 buf << wsName;
312 buf << wsAttrs;
313 if (wsChildren.IsEmpty()) {
314 buf << L"\n/>";
315 } else {
316 buf << L"\n>";
317 buf << wsChildren;
318 buf << L"</";
319 buf << wsElement;
320 buf << L"\n>";
321 }
322 }
323 }
324
RegenerateFormFile_Container(CXFA_Node * pNode,const CFX_RetainPtr<IFGAS_Stream> & pStream,bool bSaveXML=false)325 void RegenerateFormFile_Container(CXFA_Node* pNode,
326 const CFX_RetainPtr<IFGAS_Stream>& pStream,
327 bool bSaveXML = false) {
328 XFA_Element eType = pNode->GetElementType();
329 if (eType == XFA_Element::Field || eType == XFA_Element::Draw ||
330 !pNode->IsContainerNode()) {
331 CFX_WideTextBuf buf;
332 RegenerateFormFile_Changed(pNode, buf, bSaveXML);
333 FX_STRSIZE nLen = buf.GetLength();
334 if (nLen > 0)
335 pStream->WriteString((const FX_WCHAR*)buf.GetBuffer(), nLen);
336 return;
337 }
338
339 CFX_WideStringC wsElement = pNode->GetClassName();
340 pStream->WriteString(L"<", 1);
341 pStream->WriteString(wsElement.c_str(), wsElement.GetLength());
342 CFX_WideString wsOutput;
343 SaveAttribute(pNode, XFA_ATTRIBUTE_Name, L"name", true, wsOutput);
344 CFX_WideString wsAttrs;
345 int32_t iAttrs = 0;
346 const uint8_t* pAttrs =
347 XFA_GetElementAttributes(pNode->GetElementType(), iAttrs);
348 while (iAttrs--) {
349 const XFA_ATTRIBUTEINFO* pAttr =
350 XFA_GetAttributeByID((XFA_ATTRIBUTE)pAttrs[iAttrs]);
351 if (pAttr->eName == XFA_ATTRIBUTE_Name)
352 continue;
353
354 CFX_WideString wsAttr;
355 SaveAttribute(pNode, pAttr->eName, pAttr->pName, false, wsAttr);
356 wsOutput += wsAttr;
357 }
358
359 if (!wsOutput.IsEmpty())
360 pStream->WriteString(wsOutput.c_str(), wsOutput.GetLength());
361
362 CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
363 if (pChildNode) {
364 pStream->WriteString(L"\n>", 2);
365 while (pChildNode) {
366 RegenerateFormFile_Container(pChildNode, pStream, bSaveXML);
367 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
368 }
369 pStream->WriteString(L"</", 2);
370 pStream->WriteString(wsElement.c_str(), wsElement.GetLength());
371 pStream->WriteString(L"\n>", 2);
372 } else {
373 pStream->WriteString(L"\n/>", 3);
374 }
375 }
376
377 } // namespace
378
XFA_DataExporter_RegenerateFormFile(CXFA_Node * pNode,const CFX_RetainPtr<IFGAS_Stream> & pStream,const FX_CHAR * pChecksum,bool bSaveXML)379 void XFA_DataExporter_RegenerateFormFile(
380 CXFA_Node* pNode,
381 const CFX_RetainPtr<IFGAS_Stream>& pStream,
382 const FX_CHAR* pChecksum,
383 bool bSaveXML) {
384 if (pNode->IsModelNode()) {
385 static const FX_WCHAR s_pwsTagName[] = L"<form";
386 static const FX_WCHAR s_pwsClose[] = L"</form\n>";
387 pStream->WriteString(s_pwsTagName, FXSYS_wcslen(s_pwsTagName));
388 if (pChecksum) {
389 static const FX_WCHAR s_pwChecksum[] = L" checksum=\"";
390 CFX_WideString wsChecksum = CFX_WideString::FromUTF8(pChecksum);
391 pStream->WriteString(s_pwChecksum, FXSYS_wcslen(s_pwChecksum));
392 pStream->WriteString(wsChecksum.c_str(), wsChecksum.GetLength());
393 pStream->WriteString(L"\"", 1);
394 }
395 pStream->WriteString(L" xmlns=\"", FXSYS_wcslen(L" xmlns=\""));
396 const FX_WCHAR* pURI = XFA_GetPacketByIndex(XFA_PACKET_Form)->pURI;
397 pStream->WriteString(pURI, FXSYS_wcslen(pURI));
398 CFX_WideString wsVersionNumber;
399 RecognizeXFAVersionNumber(
400 ToNode(pNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Template)),
401 wsVersionNumber);
402 if (wsVersionNumber.IsEmpty())
403 wsVersionNumber = L"2.8";
404
405 wsVersionNumber += L"/\"\n>";
406 pStream->WriteString(wsVersionNumber.c_str(), wsVersionNumber.GetLength());
407 CXFA_Node* pChildNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
408 while (pChildNode) {
409 RegenerateFormFile_Container(pChildNode, pStream);
410 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
411 }
412 pStream->WriteString(s_pwsClose, FXSYS_wcslen(s_pwsClose));
413 } else {
414 RegenerateFormFile_Container(pNode, pStream, bSaveXML);
415 }
416 }
417
XFA_DataExporter_DealWithDataGroupNode(CXFA_Node * pDataNode)418 void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode) {
419 if (!pDataNode || pDataNode->GetElementType() == XFA_Element::DataValue)
420 return;
421
422 int32_t iChildNum = 0;
423 for (CXFA_Node* pChildNode = pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild);
424 pChildNode;
425 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
426 iChildNum++;
427 XFA_DataExporter_DealWithDataGroupNode(pChildNode);
428 }
429
430 if (pDataNode->GetElementType() != XFA_Element::DataGroup)
431 return;
432
433 if (iChildNum > 0) {
434 CFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode();
435 ASSERT(pXMLNode->GetType() == FDE_XMLNODE_Element);
436 CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode);
437 if (pXMLElement->HasAttribute(L"xfa:dataNode"))
438 pXMLElement->RemoveAttribute(L"xfa:dataNode");
439
440 return;
441 }
442
443 CFDE_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode();
444 ASSERT(pXMLNode->GetType() == FDE_XMLNODE_Element);
445 static_cast<CFDE_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode",
446 L"dataGroup");
447 }
448
CXFA_DataExporter(CXFA_Document * pDocument)449 CXFA_DataExporter::CXFA_DataExporter(CXFA_Document* pDocument)
450 : m_pDocument(pDocument) {
451 ASSERT(m_pDocument);
452 }
453
Export(const CFX_RetainPtr<IFX_SeekableWriteStream> & pWrite)454 bool CXFA_DataExporter::Export(
455 const CFX_RetainPtr<IFX_SeekableWriteStream>& pWrite) {
456 return Export(pWrite, m_pDocument->GetRoot(), 0, nullptr);
457 }
458
Export(const CFX_RetainPtr<IFX_SeekableWriteStream> & pWrite,CXFA_Node * pNode,uint32_t dwFlag,const FX_CHAR * pChecksum)459 bool CXFA_DataExporter::Export(
460 const CFX_RetainPtr<IFX_SeekableWriteStream>& pWrite,
461 CXFA_Node* pNode,
462 uint32_t dwFlag,
463 const FX_CHAR* pChecksum) {
464 ASSERT(pWrite);
465 if (!pWrite)
466 return false;
467
468 CFX_RetainPtr<IFGAS_Stream> pStream = IFGAS_Stream::CreateStream(
469 pWrite,
470 FX_STREAMACCESS_Text | FX_STREAMACCESS_Write | FX_STREAMACCESS_Append);
471 if (!pStream)
472 return false;
473
474 pStream->SetCodePage(FX_CODEPAGE_UTF8);
475 return Export(pStream, pNode, dwFlag, pChecksum);
476 }
477
Export(const CFX_RetainPtr<IFGAS_Stream> & pStream,CXFA_Node * pNode,uint32_t dwFlag,const FX_CHAR * pChecksum)478 bool CXFA_DataExporter::Export(const CFX_RetainPtr<IFGAS_Stream>& pStream,
479 CXFA_Node* pNode,
480 uint32_t dwFlag,
481 const FX_CHAR* pChecksum) {
482 CFDE_XMLDoc* pXMLDoc = m_pDocument->GetXMLDoc();
483 if (pNode->IsModelNode()) {
484 switch (pNode->GetPacketID()) {
485 case XFA_XDPPACKET_XDP: {
486 static const FX_WCHAR s_pwsPreamble[] =
487 L"<xdp:xdp xmlns:xdp=\"http://ns.adobe.com/xdp/\">";
488 pStream->WriteString(s_pwsPreamble, FXSYS_wcslen(s_pwsPreamble));
489 for (CXFA_Node* pChild = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
490 pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
491 Export(pStream, pChild, dwFlag, pChecksum);
492 }
493 static const FX_WCHAR s_pwsPostamble[] = L"</xdp:xdp\n>";
494 pStream->WriteString(s_pwsPostamble, FXSYS_wcslen(s_pwsPostamble));
495 break;
496 }
497 case XFA_XDPPACKET_Datasets: {
498 CFDE_XMLElement* pElement =
499 static_cast<CFDE_XMLElement*>(pNode->GetXMLMappingNode());
500 if (!pElement || pElement->GetType() != FDE_XMLNODE_Element)
501 return false;
502
503 CXFA_Node* pDataNode = pNode->GetNodeItem(XFA_NODEITEM_FirstChild);
504 ASSERT(pDataNode);
505 XFA_DataExporter_DealWithDataGroupNode(pDataNode);
506 pXMLDoc->SaveXMLNode(pStream, pElement);
507 break;
508 }
509 case XFA_XDPPACKET_Form: {
510 XFA_DataExporter_RegenerateFormFile(pNode, pStream, pChecksum);
511 break;
512 }
513 case XFA_XDPPACKET_Template:
514 default: {
515 CFDE_XMLElement* pElement =
516 static_cast<CFDE_XMLElement*>(pNode->GetXMLMappingNode());
517 if (!pElement || pElement->GetType() != FDE_XMLNODE_Element)
518 return false;
519
520 pXMLDoc->SaveXMLNode(pStream, pElement);
521 break;
522 }
523 }
524 return true;
525 }
526
527 CXFA_Node* pDataNode = pNode->GetNodeItem(XFA_NODEITEM_Parent);
528 CXFA_Node* pExportNode = pNode;
529 for (CXFA_Node* pChildNode = pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild);
530 pChildNode;
531 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
532 if (pChildNode != pNode) {
533 pExportNode = pDataNode;
534 break;
535 }
536 }
537 CFDE_XMLElement* pElement =
538 static_cast<CFDE_XMLElement*>(pExportNode->GetXMLMappingNode());
539 if (!pElement || pElement->GetType() != FDE_XMLNODE_Element)
540 return false;
541
542 XFA_DataExporter_DealWithDataGroupNode(pExportNode);
543 pElement->SetString(L"xmlns:xfa", L"http://www.xfa.org/schema/xfa-data/1.0/");
544 pXMLDoc->SaveXMLNode(pStream, pElement);
545 pElement->RemoveAttribute(L"xmlns:xfa");
546
547 return true;
548 }
549