Skip to content

Commit

Permalink
feat(internal): marshal self-closing tags in XML (#1225)
Browse files Browse the repository at this point in the history
Currently self-closing tags are marshaled as `<a></a>` which is not the
preferred format `<a/>`.

With the current implementation of `encoding/xml`, self-closing tags are
expanded to `StartElement` and `EndElement` so both elements are written
to output.

In this PR, a field `Empty` is added to both elements to indicate
whether the current element is empty. During encoding:
 - `/` is written before `>` for an empty `StartElement`
 - nothing will be written for an empty `EndElement`

Considering that we only want tabs not being escaped, this PR modifies
`escapeNewline` to `escapeWhitespace` to indicate if we want all
whitespace characters escaped.
  • Loading branch information
cuixq authored Sep 10, 2024
1 parent 07619c0 commit b402733
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 159 deletions.
2 changes: 2 additions & 0 deletions internal/resolution/manifest/__snapshots__/maven_test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<groupId>org.example</groupId>
<artifactId>abc</artifactId>
<version>1.0.1</version>
<optional/>
</dependency>
<dependency>
<groupId>org.example</groupId>
Expand Down Expand Up @@ -186,6 +187,7 @@
<groupId>org.example</groupId>
<artifactId>abc</artifactId>
<version>1.0.2</version>
<optional/>
</dependency>
<dependency>
<groupId>org.example</groupId>
Expand Down
1 change: 1 addition & 0 deletions internal/resolution/manifest/fixtures/maven/my-app/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<groupId>org.example</groupId>
<artifactId>abc</artifactId>
<version>1.0.1</version>
<optional/>
</dependency>
<dependency>
<groupId>org.example</groupId>
Expand Down
30 changes: 19 additions & 11 deletions internal/thirdparty/xml/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,11 @@ func (enc *Encoder) EncodeToken(t Token) error {
return err
}
case EndElement:
if err := p.writeEnd(t.Name); err != nil {
if err := p.writeEnd(t.Name, t.Empty); err != nil {
return err
}
case CharData:
p.Write(t)
escapeText(p, t, false)
case Comment:
if bytes.Contains(t, endComment) {
return fmt.Errorf("xml: EncodeToken of Comment containing --> marker")
Expand Down Expand Up @@ -495,6 +495,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
if startTemplate != nil {
start.Name = startTemplate.Name
start.Attr = append(start.Attr, startTemplate.Attr...)
start.Empty = startTemplate.Empty
} else if tinfo.xmlname != nil {
xmlname := tinfo.xmlname
if xmlname.name != "" {
Expand Down Expand Up @@ -569,7 +570,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
return err
}

if err := p.writeEnd(start.Name); err != nil {
if err := p.writeEnd(start.Name, start.Empty); err != nil {
return err
}

Expand Down Expand Up @@ -712,7 +713,7 @@ func (p *printer) marshalTextInterface(val encoding.TextMarshaler, start StartEl
return err
}
EscapeText(p, text)
return p.writeEnd(start.Name)
return p.writeEnd(start.Name, start.Empty)
}

// writeStart writes the given start element.
Expand Down Expand Up @@ -750,11 +751,16 @@ func (p *printer) writeStart(start *StartElement) error {
p.EscapeString(attr.Value)
p.WriteByte('"')
}

if start.Empty {
p.WriteByte('/')
}

p.WriteByte('>')
return nil
}

func (p *printer) writeEnd(name Name) error {
func (p *printer) writeEnd(name Name, empty bool) error {
if name.Local == "" {
return fmt.Errorf("xml: end tag with no name")
}
Expand All @@ -769,11 +775,13 @@ func (p *printer) writeEnd(name Name) error {
}
p.tags = p.tags[:len(p.tags)-1]

p.writeIndent(-1)
p.WriteByte('<')
p.WriteByte('/')
p.WriteString(name.Local)
p.WriteByte('>')
if !empty {
p.writeIndent(-1)
p.WriteByte('<')
p.WriteByte('/')
p.WriteString(name.Local)
p.WriteByte('>')
}
p.popPrefix()
return nil
}
Expand Down Expand Up @@ -1087,7 +1095,7 @@ func (s *parentStack) trim(parents []string) error {
}
}
for i := len(s.stack) - 1; i >= split; i-- {
if err := s.p.writeEnd(Name{Local: s.stack[i]}); err != nil {
if err := s.p.writeEnd(Name{Local: s.stack[i]}, false); err != nil {
return err
}
}
Expand Down
Loading

0 comments on commit b402733

Please sign in to comment.