Found this function somewhere, but it has a bug for the first line and comments, it places the first tag right after the header.
can someone look at it please? Test xml code included
[code=autohotkey file=Script.ahk]#NoEnv
#SingleInstance force
xml_content=
(
<?xml version="1.0" encoding="UTF-8"?>
<!--
-comment
-->
<root>
<books>
<book_1>book 1</book_1>
<book_2>book 2</book_2>
</books>
<animals>
<book_1>birds</book_1>
<book_2>fish</book_2>
</animals>
</root>
)
xml_content_2=
(
<?xml version="1.0" encoding="UTF-8"?>
<root>
<books>
<book_1>book 1</book_1>
<book_2>book 2</book_2>
</books>
<animals>
<book_1>birds</book_1>
<book_2>fish</book_2>
</animals>
</root>
)
msgBox, % xml_prettifier(xml_content)
msgBox, % xml_prettifier(xml_content_2)
ExitApp
xml_prettifier(XML, Tab="`t"){
oel := ErrorLevel, PrevCloseTag := 0, tabs := "", tablen := StrLen( tab )
StringLen, pos, XML
Loop, Parse, XML, <, % "`t`r`n "
If ( A_Index = 1 )
VarSetCapacity( XML, pos, 0 )
Else
{
StringGetPos, pos, A_LoopField, >
StringMid, b, A_LoopField, pos, 1
StringLeft, a, A_LoopField, 1
If !( OpenTag := a != "/" ) * ( CloseTag := a = "/" || a = "!" || a = "?" || b = "/" )
StringTrimRight, tabs, tabs, tablen
XML .= ( OpenTag || PrevCloseTag ? tabs : "" ) "<" A_LoopField
If !( PrevCloseTag := CloseTag ) * OpenTag
tabs := ( tabs = "" ? "`n" : tabs ) tab
}
Return XML, ErrorLevel := oel
}[/code]
xml prettifier
Re: xml prettifier
Here's an alternative pretty-printer:
Code: Select all
xml_content =
(LTrim Join
<?xml version="1.0" encoding="UTF-8"?>
<!--
-comment
-->
<root>
<books>
<book_1>book 1</book_1>
<book_2>book 2</book_2>
</books>
<animals>
<book_1>birds</book_1>
<book_2>fish</book_2>
</animals>
</root>
)
MsgBox, % "BEFORE:`n`n" . xml_content
MsgBox, % "AFTER:`n`n" . xml_prettify(xml_content, " ") ; specify any char to use as indentation
return
xml_prettify(xml_source, indent:="`t") {
static xsl, style
if !xsl {
style := "
(LTrim Join
<?xml version='1.0' encoding='ISO-8859-15'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<xsl:output method='xml'/>
<xsl:template match='@*'>
<xsl:copy/>
</xsl:template>
<xsl:template match='text()'>
<xsl:value-of select='normalize-space(.)' />
</xsl:template>
<xsl:template match='*'>
<xsl:param name='indent' select='""""'/>
<xsl:text>
</xsl:text>
<xsl:value-of select='$indent' />
<xsl:copy>
<!--<xsl:apply-templates select='@*|*|text()'>-->
<xsl:apply-templates select='@*|node()'>
<xsl:with-param name='indent' select='concat($indent, "" "")'/>
</xsl:apply-templates>
</xsl:copy>
<xsl:if test='count(../*)>0 and ../*[last()]=.'>
<xsl:text>
</xsl:text>
<xsl:value-of select='substring($indent,3)' />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
)"
xsl := ComObjCreate("MSXML2.DOMDocument.6.0")
xsl.async := false
xsl.loadXML(style)
}
a := xsl.selectSingleNode("//*[local-name()='with-param'][@name='indent']/@select")
a.value := "concat($indent, """ . indent . """)"
b := xsl.selectSingleNode("//*[local-name()='if']/*[local-name()='value-of']/@select")
b.value := "substring($indent," . StrLen(indent)+1 . ")"
xml := ComObjCreate("MSXML2.DOMDocument.6.0")
xml.async := false
xml.loadXML(xml_source)
pretty_xml := xml.transformNode(xsl)
;xml.transformNodeToObject(xsl, xml) ; does not work if indent char is whitespace??
;pretty_xml := xml.xml
return pretty_xml
}
Re: xml prettifier
Thanks for trying to help, but your solution is not really what i want, its stripping comments, spaces and probably tabs off whats in between the tags :/
I just need it to make it pretty.
I just need it to make it pretty.
Re: xml prettifier
Try this: (not tested extensively)
Code: Select all
src_1 =
(Join
<?xml version="1.0" encoding="UTF-8"?>
<!--
-comment
-->
<root>
<books>
<book_1>book 1</book_1>
<book_2>book 2</book_2>
</books>
<animals>
<book_1>birds</book_1>
<book_2>fish</book_2>
</animals>
</root>
)
src_2 =
(
<?xml version="1.0" encoding="UTF-8"?>
<root>
<books>
<book_1>book 1</book_1>
<book_2>book 2</book_2>
</books>
<animals>
<book_1>birds</book_1>
<book_2>fish</book_2>
</animals>
</root>
)
MsgBox, % xml_prettify(src_1, " ")
MsgBox, % xml_prettify(src_2, "`t")
xml_prettify(node, i:=" ", lvl:=0) {
if !IsObject(node) {
x := ComObjCreate("MSXML2.DOMDocument.6.0")
x.async := false, x.loadXML(node)
return xml_prettify(x)
}
start := end := ""
if node.hasChildNodes() {
n := "`n"
Loop, % lvl
t .= i
if (node.nodeTypeString == "element") {
start := SubStr(node.xml, 1, InStr(node.xml, ">"))
end := SubStr(node.xml, InStr(node.xml, "<",, 0))
}
for c in node.childNodes {
try val := c.selectNodes("child::node()[not(self::text())]").length
? xml_prettify(c, i, lvl+1)
: c.xml
catch
val := c.xml
str .= val . n . t
}
str := (lvl ? n . t : "") . Trim(str, ",`n`t ") . n . SubStr(t, StrLen(i)+1)
} else str := node.xml
return start . str . end
}
Re: xml prettifier
Yeah, that looks like my code. Here's the updated function:
Code: Select all
sXML_Pretty( XML, IndentationUnit="`t" ) { ; Adds linefeeds (LF, asc 10) and indentation between XML tags.
; NOTE: If the XML does not begin with a "<?xml...?>" tag, the output will begin with a newline.
StringLen, il, IndentationUnit
Loop, Parse, XML, <
If ( A_Index = 1 )
VarSetCapacity( XML, Round( StrLen( XML ) * ( A_IsUnicode ? 2.3 : 1.15 ) ), 0 )
Else
Loop, Parse, A_LoopField, >, % "`t`n`r " Chr( 160 )
If ( A_Index = 1 )
{
closetag := SubStr( A_LoopField, 1, 1 )
emptytag := SubStr( A_LoopField, 0 )
If ( closetag = "?" ) && ( emptytag = "?" )
XML := "<" A_LoopField
Else
{
If ( closetag = "/" )
{
StringTrimRight, indent, indent, il
If ( priortag )
XML .= "`n" indent
}
Else
{
XML .= "`n" indent
If ( emptytag != "/" ) && ( closetag != "!" )
indent .= IndentationUnit
}
XML .= "<" A_LoopField
}
priortag := closetag = "/" || closetag = "!" || emptytag = "/"
}
Else
XML .= ">" A_LoopField
Return XML
} ; END - sXML_Pretty( XML, IndentationUnit="`t" )
Who is online
Users browsing this forum: Endion, Google [Bot], Insanibaccha, PsysimSV and 208 guests