go-xmlfmt / xmlfmt

Go XML Formatter (Beautifier)
MIT License
51 stars 5 forks source link

Auto adds `\n` before a close tag(not what I want) #6

Closed xiebruce closed 1 year ago

xiebruce commented 2 years ago
package main

import (
    "fmt"
    "io/ioutil"

    "github.com/go-xmlfmt/xmlfmt"
)

func main() {
    xmlfile := "/Users/bruce/Downloads/example.fcpxml"
    b, _ := ioutil.ReadFile(xmlfile)
    xml := xmlfmt.FormatXML(string(b), "", "    ")
    fmt.Println(xml)
}

xmlfmt.FormatXML() auto adds a \n before </text-style> image

Here is the contents of example.fcpxml, there's no \n before </text-style>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fcpxml>
<fcpxml version="1.10">
    <resources>
        <format id="r1" name="FFVideoFormat_1920x1080_30p" frameDuration="100/3000s" width="1920" height="1080" colorSpace="1-1-1 (Rec. 709)"/>
        <effect id="r2" name="Basic Title" uid=".../Titles.localized/Bumper:Opener.localized/Basic Title.localized/Basic Title.moti"/>
    </resources>
    <library location="file:///Users/bruce/Movies/Untitled.fcpbundle/">
        <event name="Titles Event" uid="0F964C4C-82A5-40FC-873A-115B5F5F134D">
            <project name="202202062300" uid="6CDE04AC-E1FD-41FE-BFBE-34332D019BB4" modDate="2022-02-07 00:14:53 +0800">
                <sequence format="r1" duration="13000/3000s" tcStart="0s" tcFormat="NDF" renderFormat="FFRenderFormatProRes422HQ" audioLayout="stereo" audioRate="48k">
                    <spine>
                        <gap name="Gap" offset="0s" start="3600s" duration="13000/3000s">
                            <title name="Default Title - Basic Title" lane="1" offset="10800700/3000s" ref="r2" duration="3000/3000s" start="3600s">
                                <param name="Flatten" key="9999/999166631/999166633/2/351" value="1"/>
                                <param name="Alignment" key="9999/999166631/999166633/2/354/999169573/401" value="1 (Center)"/>
                                <param name="Position" key="9999/999166631/999166633/1/100/101" value="0 20.631"/>
                                <text>
                                    <text-style ref="ts1">Default Title</text-style>
                                </text>
                                <text-style-def id="ts1">
                                    <text-style font="DFP King Gothic GB Medium" fontSize="56" fontFace="Regular" fontColor="1 1 1 1" alignment="center"/>
                                </text-style-def>
                            </title>
                            <title name="Default Title - Basic Title" lane="1" offset="10805200/3000s" ref="r2" duration="3100/3000s" start="3600s">
                                <param name="Flatten" key="9999/999166631/999166633/2/351" value="1"/>
                                <param name="Alignment" key="9999/999166631/999166633/2/354/999169573/401" value="1 (Center)"/>
                                <param name="Position" key="9999/999166631/999166633/1/100/101" value="0 20.631"/>
                                <text>
                                    <text-style ref="ts2">Default Title</text-style>
                                </text>
                                <text-style-def id="ts2">
                                    <text-style font="DFP King Gothic GB Medium" fontSize="56" fontFace="Regular" fontColor="1 1 1 1" alignment="center"/>
                                </text-style-def>
                            </title>
                            <title name="Default Title - Basic Title" lane="1" offset="10810200/3000s" ref="r2" duration="2800/3000s" start="3600s">
                                <param name="Flatten" key="9999/999166631/999166633/2/351" value="1"/>
                                <param name="Alignment" key="9999/999166631/999166633/2/354/999169573/401" value="1 (Center)"/>
                                <param name="Position" key="9999/999166631/999166633/1/100/101" value="0 20.631"/>
                                <text>
                                    <text-style ref="ts3">Default Title</text-style>
                                </text>
                                <text-style-def id="ts3">
                                    <text-style font="DFP King Gothic GB Medium" fontSize="56" fontFace="Regular" fontColor="1 1 1 1" alignment="center"/>
                                </text-style-def>
                            </title>
                        </gap>
                    </spine>
                </sequence>
            </project>
        </event>
        <smart-collection name="Favorites" match="all">
            <match-ratings value="favorites"/>
        </smart-collection>
        <smart-collection name="Stills" match="all">
            <match-media rule="is" type="stills"/>
        </smart-collection>
        <smart-collection name="All Videos" match="any">
            <match-media rule="is" type="videoOnly"/>
            <match-media rule="is" type="videoWithAudio"/>
        </smart-collection>
        <smart-collection name="Audio Only" match="all">
            <match-media rule="is" type="audioOnly"/>
        </smart-collection>
        <smart-collection name="Project" match="all">
            <match-clip rule="is" type="project"/>
        </smart-collection>
    </library>
</fcpxml>
AntonioSun commented 2 years ago

If I understand you correctly, you want that

<text-style ref="ts3">Default Title</text-style>

be kept on the same line while the other tags separated in different lines as of now, right?

xiebruce commented 2 years ago

If I understand you correctly, you want that

<text-style ref="ts3">Default Title</text-style>

be kept on the same line while the other tags separated in different lines as of now, right?

Yes!

it should be this

<text-style ref="ts2">Default Title</text-style>

not this(which is currently happening):

<text-style ref="ts2">Default Title
</text-style>
AntonioSun commented 2 years ago

Do you have an idea how to do that?

The way I view it -- it is what it is, i.e., you can't have some random tags on the same line while others don't. A program logic doesn't work that way.

It is not 100% impossible, but I'm reluctant to put in my effort on something I view as useless. If this is so important to you, hope that it can give you enough incentive to scratch your own itches, and send in PR hopefully. (however, if the solution is not elegant enough, or it is taking too much percentage of code (say 2%), I might not take it in to maintain it).

The other option you have is, since your xml is only of version 1, with no name spaces, you can just go through the decoding and encoding procedures. But I doubt that the standard output will give what you want either.

AntonioSun commented 2 years ago

It is not 100% impossible...

In other words, I view the implementation would be messy and bulky, just to solve such a trivial thing.
But feel free to enlighten me.

xiebruce commented 2 years ago

you can't have some random tags on the same line while others don't.

Yes, I agree, maybe just leave it, for now I'm replacing the \n and spaces(\s) using RegExp

r_inside_whitespace := regexp.MustCompile(`[\s\p{Zs}]+(</text-style>)`)
xml = r_inside_whitespace.ReplaceAllString(xml, "$1")
chenbihao commented 2 years ago

I prefer this:

// end elem
if strings.HasPrefix(m, "</") {
      indentLevel--
      return m
}

But the previous elem did not wrap,like this:

<MZBRCF>
    <CFID>6083</CFID></MZBRCF>
<MZBRCF>
    <CFID>6084</CFID>
    ...

So I changed it:

func replaceTag(prefix, indent string) func(string) string {
    indentLevel := 0
    lastEndElem := true
    return func(m string) string {
        ...
        // end elem
        if strings.HasPrefix(m, "</") {
            indentLevel--
            if lastEndElem {
                return NL + prefix + strings.Repeat(indent, indentLevel) + m
            }
            lastEndElem = true
            return m
        } else {
            lastEndElem = false
        }
        defer func() {
            indentLevel++
        }()
        return NL + prefix + strings.Repeat(indent, indentLevel) + m
    }
}

So I changed it:

<?xml version="1.0" encoding="UTF-8"?>
<MZBRCFS>
  <MZBRCF>
    <CFID>6078</CFID>
  </MZBRCF>
  <MZBRCF>
    <CFID>6079</CFID>
  </MZBRCF>
</MZBRCFS>
AntonioSun commented 2 years ago

Hmm, thanks.

Would you send a PR please? which should include the following two/three steps,

Thanks & looking forward to your PR.

chenbihao commented 2 years ago

Okay, I'm testing it.

AntonioSun commented 2 years ago

yeah, that extra space at the end, I think you've got it. :+1:

AntonioSun commented 1 year ago

7 should have fixed it, thus closing it.

LMK otherwise.