11using DocumentFormat . OpenXml ;
22using DocumentFormat . OpenXml . Packaging ;
33using DocumentFormat . OpenXml . Spreadsheet ;
4+ using W = DocumentFormat . OpenXml . Wordprocessing ;
5+ using A = DocumentFormat . OpenXml . Drawing ;
6+ using DW = DocumentFormat . OpenXml . Drawing . Wordprocessing ;
7+ using PIC = DocumentFormat . OpenXml . Drawing . Pictures ;
48
59[ TestFixture ]
610public class OpenXmlTests
@@ -14,6 +18,126 @@ public Task FixesPrefixedNamespace()
1418 return VerifyZip ( result ) ;
1519 }
1620
21+ [ Test ]
22+ public void SvgBlipEmbedIdsAreRemapped ( )
23+ {
24+ var docxStream = CreateDocxWithSvg ( ) ;
25+ var result = DeterministicPackage . Convert ( docxStream ) ;
26+
27+ result . Position = 0 ;
28+ using var archive = new Archive ( result , ZipArchiveMode . Read ) ;
29+
30+ // Collect relationship IDs from .rels
31+ var relsEntry = archive . GetEntry ( "word/_rels/document.xml.rels" ) ! ;
32+ using var relsStream = relsEntry . Open ( ) ;
33+ var relsXml = XDocument . Load ( relsStream ) ;
34+ var relIds = relsXml . Root ! . Elements ( )
35+ . Select ( _ => _ . Attribute ( "Id" ) ! . Value )
36+ . ToList ( ) ;
37+
38+ // Collect r:embed references from document.xml
39+ var docEntry = archive . GetEntry ( "word/document.xml" ) ! ;
40+ using var docStream = docEntry . Open ( ) ;
41+ var docXml = XDocument . Load ( docStream ) ;
42+ XNamespace r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" ;
43+ var embedRefs = docXml . Descendants ( ) . Attributes ( r + "embed" )
44+ . Select ( _ => _ . Value )
45+ . ToList ( ) ;
46+
47+ // Every r:embed reference must exist in the .rels file
48+ foreach ( var embedRef in embedRefs )
49+ {
50+ Assert . That ( relIds , Does . Contain ( embedRef ) ,
51+ $ "r:embed=\" { embedRef } \" in document.xml has no matching relationship ID in .rels") ;
52+ }
53+ }
54+
55+ [ Test ]
56+ public Task SvgBlipDocx ( )
57+ {
58+ var docxStream = CreateDocxWithSvg ( ) ;
59+ var result = DeterministicPackage . Convert ( docxStream ) ;
60+
61+ return Verify ( result , extension : "docx" )
62+ . UniqueForRuntime ( ) ;
63+ }
64+
65+ internal static MemoryStream CreateDocxWithSvg ( )
66+ {
67+ var stream = new MemoryStream ( ) ;
68+ using ( var document = WordprocessingDocument . Create ( stream , WordprocessingDocumentType . Document ) )
69+ {
70+ var mainPart = document . AddMainDocumentPart ( ) ;
71+
72+ // Add PNG fallback
73+ var pngPart = mainPart . AddImagePart ( "image/png" , "rPng1" ) ;
74+ var pngBytes = Convert . FromBase64String (
75+ "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAAEElEQVR4nGP4z8AARAwQCgAf7gP9i18U1AAAAABJRU5ErkJggg==" ) ;
76+ using ( var ms = new MemoryStream ( pngBytes ) )
77+ {
78+ pngPart . FeedData ( ms ) ;
79+ }
80+
81+ // Add SVG
82+ var svgPart = mainPart . AddImagePart ( "image/svg+xml" , "rSvg1" ) ;
83+ var svgBytes = System . Text . Encoding . UTF8 . GetBytes (
84+ """<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><circle cx="50" cy="50" r="40" fill="red" /></svg>""" ) ;
85+ using ( var ms = new MemoryStream ( svgBytes ) )
86+ {
87+ svgPart . FeedData ( ms ) ;
88+ }
89+
90+ // Build blip with SVG extension
91+ var blip = new A . Blip { Embed = "rPng1" } ;
92+ var svgBlipElement = new OpenXmlUnknownElement ( "asvg" , "svgBlip" , "http://schemas.microsoft.com/office/drawing/2016/SVG/main" ) ;
93+ svgBlipElement . SetAttribute ( new OpenXmlAttribute ( "r" , "embed" , "http://schemas.openxmlformats.org/officeDocument/2006/relationships" , "rSvg1" ) ) ;
94+ var ext = new OpenXmlUnknownElement ( "a" , "ext" , "http://schemas.openxmlformats.org/drawingml/2006/main" ) ;
95+ ext . SetAttribute ( new OpenXmlAttribute ( "" , "uri" , "" , "{96DAC541-7B7A-43D3-8B79-37D633B846F1}" ) ) ;
96+ ext . Append ( svgBlipElement ) ;
97+ var extList = new OpenXmlUnknownElement ( "a" , "extLst" , "http://schemas.openxmlformats.org/drawingml/2006/main" ) ;
98+ extList . Append ( ext ) ;
99+ blip . Append ( extList ) ;
100+
101+ var drawing = new W . Drawing (
102+ new DW . Inline (
103+ new DW . Extent { Cx = 952500 , Cy = 952500 } ,
104+ new DW . DocProperties { Id = 1U , Name = "Image" } ,
105+ new A . Graphic (
106+ new A . GraphicData (
107+ new PIC . Picture (
108+ new PIC . NonVisualPictureProperties (
109+ new PIC . NonVisualDrawingProperties { Id = 0U , Name = "Image" } ,
110+ new PIC . NonVisualPictureDrawingProperties ( ) ) ,
111+ new PIC . BlipFill ( blip , new A . Stretch ( new A . FillRectangle ( ) ) ) ,
112+ new PIC . ShapeProperties (
113+ new A . Transform2D (
114+ new A . Offset { X = 0 , Y = 0 } ,
115+ new A . Extents { Cx = 952500 , Cy = 952500 } ) ,
116+ new A . PresetGeometry ( new A . AdjustValueList ( ) ) { Preset = A . ShapeTypeValues . Rectangle } ) ) )
117+ { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" } )
118+ )
119+ {
120+ DistanceFromTop = 0U ,
121+ DistanceFromBottom = 0U ,
122+ DistanceFromLeft = 0U ,
123+ DistanceFromRight = 0U
124+ } ) ;
125+
126+ var body = new W . Body (
127+ new W . Paragraph (
128+ new W . Run (
129+ new W . Text ( "Before SVG" ) { Space = SpaceProcessingModeValues . Preserve } ) ) ,
130+ new W . Paragraph ( new W . Run ( drawing ) ) ,
131+ new W . Paragraph (
132+ new W . Run (
133+ new W . Text ( "After SVG" ) { Space = SpaceProcessingModeValues . Preserve } ) ) ) ;
134+ mainPart . Document = new W . Document ( body ) ;
135+ }
136+
137+ stream . Position = 0 ;
138+ return stream ;
139+ }
140+
17141 static MemoryStream CreateSpreadsheet ( )
18142 {
19143 var stream = new MemoryStream ( ) ;
0 commit comments