USCIS 與加州法院 PDF 為何在 macOS Preview 儲存後變空白:Hybrid XFA 的運作方式
Why USCIS & California Court PDFs (I-765, I-485, I-130, FL-150) Open Blank After Saving in macOS Preview — And How Hybrid XFA Works
USCIS 及加州法院的 Hybrid XFA PDF 在 macOS Preview 儲存後,可能因 Preview 只更新 AcroForm、未更新 XFA XML,令 Windows 版 Acrobat Reader 顯示空白。
Every week in immigration law firms and California family or probate practices, the same bug plays out: a client opens an official USCIS petition (Form I-765, Form I-485, or Form I-130) or a California Judicial Council court packet (FL-150, DE-111, or CM-010) on a MacBook, fills out every page in macOS Preview, saves the file, and emails it back to the paralegal.
On the client's Mac, the PDF still looks filled out. Yet the moment the paralegal opens that attachment in Adobe Acrobat Reader on Windows—or uploads it to a court Electronic Filing Service Provider (EFSP) portal—every single text box and checkbox renders 100% blank, or the portal rejects the upload with an XFA/encryption error.
This isn't user error. It is a deterministic byte-level collision between Adobe LiveCycle / AEM Forms Hybrid XFA packets, ISO 32000-1 /AcroForm widget trees, and macOS Preview's PDFKit serializer.
In our 137 Government Forms Fillability Study, we programmatically inspected 134 public government PDFs with pypdf 6.6:
-
85.1% (114 of 134) of government forms are Hybrid XFA (
xfa_hybrid) documents containing both an/AcroFormwidget hierarchy and an/XFAXML packet array. -
92.3% (24 of 26) of analyzed USCIS forms (
I-765,I-485,I-130,I-864,I-131,N-400) are Hybrid XFA and carry owner encryption locks (/Encrypt+/Perms), averaging a median of 227 fields across 8 pages. -
76.9% (10 of 13) of California Judicial Council forms (
FL-150,CM-010,DE-111,FL-100) are Hybrid XFA, and 100% (13 of 13) carry owner permission restrictions that block document assembly and flattening.
1. Inside /Root -> /AcroForm: How Hybrid XFA PDFs Store Data Twice
When an agency authors a form in Adobe LiveCycle Designer or AEM Forms and saves it as an "Acrobat 8 (Static) XML Form PDF," the producer writes two parallel form representations inside /Catalog -> /AcroForm:
-
/Fields(ISO 32000-1 §12.7 AcroForm Widget Tree): PDF dictionary objects (/Subtype /Widget,/FT /Txor/FT /Btn) nested underform1[0].#subform[0]..., storing values in/Vand glyph streams in/AP << /N ... >>. -
/XFA(XML Forms Architecture Packet Array): An array of key-stream pairs (preamble,config,template,datasets,form,postamble) holding compressed XML streams.
Inspecting /Catalog -> /AcroForm inside USCIS Form I-765 (7 pages, 161 fields) or California FL-150 (4 pages, 262 fields) reveals both structures side by side:
1 0 obj
<<
/Type /Catalog
/Pages 3 0 R
/Perms << /UR3 4 0 R >>
/AcroForm <<
/Fields [ 12 0 R ]
/DA (/CourierStd 10 Tf 0 g)
/XFA [
(preamble) 15 0 R (config) 16 0 R
(template) 17 0 R (datasets) 18 0 R
(form) 19 0 R (postamble) 20 0 R
]
>>
>>
endobj
Stream 18 0 R (datasets) stores the <xfa:datasets> XML tree read by XFA-aware viewers:
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
<xfa:data>
<form1><Page1><Pt1Line1a_FamilyName/><Pt1Line1b_GivenName/></Page1></form1>
</xfa:data>
</xfa:datasets>
Meanwhile, the corresponding AcroForm widget dictionary inside /Fields represents the same input box for non-XFA viewers:
245 0 obj
<< /Type /Annot /Subtype /Widget /FT /Tx /T (Pt1Line1a_FamilyName[0])
/TU (Part 1. Line 1a. Family Name (Last Name))
/Rect [ 54.00 582.10 294.00 596.50 ] /V () /AP << /N 246 0 R >> >>
endobj
2. Why macOS Preview Saves Open Blank in Windows Adobe Acrobat
Apple's macOS Preview (PDFKit) does not implement an XFA XML parser. When a user fills and saves a Hybrid XFA PDF in Preview:
-
Preview ignores
/XFA: It renders and edits only the/AcroForm -> /Fieldswidget tree. -
Preview writes user input only into
/AcroForm /Fields /V: Typing intoPt1Line1a_FamilyName[0]writes/V (Smith)in the PDF incremental update trailer while leaving stream18 0 R(<xfa:datasets>) untouched and empty (<Pt1Line1a_FamilyName/>). -
Preview often omits or corrupts portable
/AP /Nappearance streams: Preview writes Apple font references or alters/NeedAppearanceswhile leaving the/XFAkey intact inside/AcroForm.
When Adobe Acrobat Reader on Windows opens a hybrid PDF that still contains /XFA, Acrobat's XFA runtime takes precedence over /AcroForm /Fields /V:
Does /Root/AcroForm contain an /XFA key?
├── YES -> Adobe Acrobat loads stream 18 0 R (<xfa:datasets>)
│ Ignores /AcroForm /Fields /V ("Smith")
│ Renders empty <xfa:datasets> XML -> 100% BLANK FIELDS
└── NO -> Standard ISO 32000-1 renderer reads /AcroForm /Fields /V
All typed values render normally
Worse: if a paralegal clicks Save in Acrobat while that blank XFA view is open, Acrobat overwrites /AcroForm /Fields /V with the empty <xfa:datasets> state—permanently erasing the client's answers.
3. Recovering "Blank" Preview PDFs & Stripping /XFA + /Perms in Python
Before re-saving a client's PDF in Acrobat, you can extract every /V value saved by macOS Preview, strip the stale /XFA packet and /Perms usage-rights lock, and regenerate appearance streams using pikepdf and pypdf:
#!/usr/bin/env python3
"""Recover macOS Preview edits from Hybrid XFA PDFs and strip /XFA + /Perms locks."""
import json, sys
from pathlib import Path
import pikepdf
from pypdf import PdfReader, PdfWriter
from pypdf.generic import BooleanObject, NameObject
def walk_values(node_ref, prefix="", out=None):
out = {} if out is None else out
node = node_ref.get_object()
name = str(node.get("/T", ""))
full = f"{prefix}.{name}" if prefix and name else (name or prefix)
if "/Kids" in node:
for kid in node["/Kids"]:
walk_values(kid, full, out)
elif node.get("/V") not in (None, "", "/Off"):
out[full] = str(node.get("/V"))
return out
def normalize_hybrid_pdf(input_pdf: str, output_pdf: str) -> dict:
tmp = Path(output_pdf).with_suffix(".tmp.pdf")
with pikepdf.open(input_pdf, password="") as pdf:
if "/Perms" in pdf.Root:
del pdf.Root["/Perms"]
if "/AcroForm" in pdf.Root and "/XFA" in pdf.Root.AcroForm:
del pdf.Root.AcroForm["/XFA"]
pdf.save(tmp)
reader = PdfReader(str(tmp))
writer = PdfWriter()
writer.append(reader)
acroform = writer._root_object[NameObject("/AcroForm")].get_object()
acroform[NameObject("/NeedAppearances")] = BooleanObject(True)
recovered = {}
for ref in acroform.get("/Fields", []):
recovered.update(walk_values(ref))
for page in writer.pages:
for annot_ref in page.get("/Annots", []):
annot = annot_ref.get_object()
if annot.get("/Subtype") == "/Widget" and annot.get("/FT") == "/Tx":
if annot.get("/V") and NameObject("/AP") in annot:
del annot[NameObject("/AP")]
with open(output_pdf, "wb") as f:
writer.write(f)
tmp.unlink(missing_ok=True)
return recovered
if __name__ == "__main__":
recovered = normalize_hybrid_pdf(sys.argv[1], sys.argv[2])
print(f"Recovered {len(recovered)} fields:", json.dumps(recovered, indent=2))
Note why deleting /Root/Perms alongside /AcroForm/XFA is mandatory: USCIS and California court PDFs include an Adobe /UR3 usage-rights signature inside /Perms. If you strip /XFA without removing /Perms, Acrobat detects a modified byte digest and blocks saving.
4. Audited USCIS & California Court Forms & Browser Workflows
| Form Code | Agency | Pages | Audited Fields | Hybrid /XFA
|
Owner /Encrypt
|
|---|---|---|---|---|---|
| Form I-765 | USCIS | 7 | 161 (119 Tx, 38 Btn, 4 Ch) |
Yes | Yes |
| Form I-130 | USCIS | 12 | 450 (302 Tx, 128 Btn, 20 Ch) |
Yes | Yes |
| Form I-485 | USCIS | 24 | 760 (334 Tx, 416 Btn, 10 Ch) |
Yes | Yes |
| Form FL-150 | CA Judicial Council | 4 | 262 (212 Tx, 50 Btn) |
Yes | Yes |
| Form CM-010 | CA Judicial Council | 3 | 84 (23 Tx, 61 Btn) |
Yes | Yes |
| Form DE-111 | CA Judicial Council | 4 | Probate Petition (Tx + Btn) |
Yes | Yes |
If you want clients or legal staff to complete these forms in Chrome, Safari, Edge, or Firefox on macOS or Windows without triggering the macOS Preview /XFA blank-fields bug—or convert locked XFA files into clean AcroForm or flattened PDFs—use these tools and audited guides:
-
XFA to Fillable PDF Unlocker: Strip
/XFAand owner locks fromDD-2875,FL-150,DE-111,CM-010,I-765, orI-485and export standard AcroForm or flattened PDFs. - USCIS Form I-765 Online Filler & Mac Preview Fix: Fill all 7 pages and 161 fields of the Employment Authorization application online with baked appearance streams.
- USCIS Form I-130 Online Petition Filler: Complete the 12-page, 450-field Petition for Alien Relative without LiveCycle input mask blocks on foreign addresses.
- USCIS Form I-485 Adjustment of Status Filler: Fill the 24-page, 760-field Adjustment of Status packet across Mac and Windows without losing field data.
-
California FL-150 Income and Expense Declaration: Complete the 4-page, 262-field California family law financial disclosure (
FL-150) alongsideCM-010andDE-111and export flattened PDFs for court EFSP e-filing. -
137 Government Forms Fillability Study: Full structural dataset of
/AcroForm,/XFA,/Encrypt, and/TUsemantics across 134 government PDFs.
Disclosure: I am the solo developer of JustFill.
AI disclosure: AI coding agents drafted and revised this article and verified the code examples above.
來源:DEV Community · dev.to