• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"&amp;";
28         break;
29       case '<':
30         textBuf << L"&lt;";
31         break;
32       case '>':
33         textBuf << L"&gt;";
34         break;
35       case '\'':
36         textBuf << L"&apos;";
37         break;
38       case '\"':
39         textBuf << L"&quot;";
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"&amp;";
58     } else if (ch == '<') {
59       textBuf << L"&lt;";
60     } else if (ch == '>') {
61       textBuf << L"&gt;";
62     } else if (ch == '\'') {
63       textBuf << L"&apos;";
64     } else if (ch == '\"') {
65       textBuf << L"&quot;";
66     } else if (ch == ' ') {
67       if (i && str.GetAt(i - 1) != ' ') {
68         textBuf.AppendChar(' ');
69       } else {
70         textBuf << L"&#x20;";
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