Jump to content
KickStarter15

Arranging XML File from one line into separate line

Recommended Posts

Hi Experts,

I need your suggestions and idea on this concern, I've been searching in the forum and help file including googling but could not find any related topic for such issue that I have😅.

I need to arrange the XML File from one line into separate line based on their parent element. Now, I don't have any clue on where to start and how to start coding. If you have any suggestions or Idea if this issue can be done by AutoIt, then that would be a great help. Please refer below:

This is the current XML that I have (no code being used it was just given to me to arrange it) and it was presented in one line. There are lots of XML files that were given to me like this and I need to arrange this just like the next sample given below.

<?xml version="1.0" encoding="utf-8"?>
<component xml_id="0002107" version="3.0" xml_lang="en" type="serialArticle" xmlns1="http://www.w3.org/2001/XMLSchema-instance">
<header>
<Data><Enabled>true</Enabled><dataType>T1</dataType><dataDetails xsi:type="Type1"><field1>name1</field1><field2>email1</field2><field3>choice1</field3><field4>choice2</field4><field5>choice3</field5><field6>choice4</field6><field7>choice5</field7><field8>choice7</field8></dataDetails><optionSetting>true</optionSetting></Data><Data><Enabled>true</Enabled><dataType>T1</dataType><dataDetails xsi:type="Type1"><field1>name2</field1><field2>email2</field2><field3>choice1</field3><field4>choice2</field4><field5>choice3</field5><field6>choice4</field6><field7>choice5</field7><field8>choice7</field8></dataDetails><optionSetting>true</optionSetting></Data><Data><Enabled>true</Enabled><dataType>T2</dataType><dataDetails xsi:type="Type2"><field1>name3</field1><field2>email3</field2><field6>choice6</field6><field8>choice7</field8></dataDetails><optionSetting>true</optionSetting></Data><Data><Enabled>true</Enabled><dataType>T1</dataType><dataDetails xsi:type="Type1"><field1>name4</field1><field2>email4</field2><field3>choice1</field3><field4>choice2</field4><field5>choice3</field5><field6>choice4</field6><field7>choice5</field7><field8>choice7</field8></dataDetails><optionSetting>true</optionSetting></Data></header></component>

 

And this is what I wanted this to be presented, each parent elements were separated with another line same with their child elements.

<?xml version="1.0" encoding="utf-8"?>
<component xml_id="0002107" version="3.0" xml_lang="en" type="serialArticle" xmlns1="http://www.w3.org/2001/XMLSchema-instance">
<header>
  <Data>
    <Enabled>true</Enabled>
    <dataType>T1</dataType>
    <dataDetails xsi:type="Type1">
      <field1>name1</field1>
      <field2>email1</field2>
      <field3>choice1</field3>
      <field4>choice2</field4>
      <field5>choice3</field5>
      <field6>choice4</field6>
      <field7>choice5</field7>
      <field8>choice7</field8>
    </dataDetails>
    <optionSetting>true</optionSetting>
  </Data>
  <Data>
    <Enabled>true</Enabled>
    <dataType>T1</dataType>
    <dataDetails xsi:type="Type1">
      <field1>name2</field1>
      <field2>email2</field2>
      <field3>choice1</field3>
      <field4>choice2</field4>
      <field5>choice3</field5>
      <field6>choice4</field6>
      <field7>choice5</field7>
      <field8>choice7</field8>
    </dataDetails>
    <optionSetting>true</optionSetting>
  </Data>
  <Data>
    <Enabled>true</Enabled>
    <dataType>T2</dataType>
    <dataDetails xsi:type="Type2">
      <field1>name3</field1>
      <field2>email3</field2>
      <field6>choice6</field6>
      <field8>choice7</field8>
    </dataDetails>
    <optionSetting>true</optionSetting>
  </Data>
  <Data>
    <Enabled>true</Enabled>
    <dataType>T1</dataType>
    <dataDetails xsi:type="Type1">
      <field1>name4</field1>
      <field2>email4</field2>
      <field3>choice1</field3>
      <field4>choice2</field4>
      <field5>choice3</field5>
      <field6>choice4</field6>
      <field7>choice5</field7>
      <field8>choice7</field8>
    </dataDetails>
    <optionSetting>true</optionSetting>
  </Data>
</header>
</component>

 

Please advise if this is possible with Autoit and suggestions are open.

Thanks in advance Experts!😂😀

 

KS15

 

 


Programming is "To make it so simple that there are obviously no deficiencies" or "To make it so complicated that there are no obvious deficiencies" by C.A.R. Hoare.

Share this post


Link to post
Share on other sites

Click here to see my signature:

Spoiler

Thoughts:

  • I will always thank you for the time you spent for me.
    I'm here to ask, and from your response, I'd like to learn.
    By my knowledge, I can help someone else, and "that someone" could help in turn another, and so on.

/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

ALWAYS GOOD TO READ:

 

Share this post


Link to post
Share on other sites

@FrancescoDiMuro, Thanks! 😄 it looks like an online converter, yup tried it and it's a good way for an alternative way as of this moment. But is there any code that I can refer to have that kind of output.


Programming is "To make it so simple that there are obviously no deficiencies" or "To make it so complicated that there are no obvious deficiencies" by C.A.R. Hoare.

Share this post


Link to post
Share on other sites

Have a look at XML.au3 by @mLipok, the function XML_Tidy does what you want, however I tried with your xml file but I can't parse the file, I couldn't parse it with XML Notepad either, I tried adding the namespace but it said it's invalid.

Unfortunately I've got to get some shuteye, work in three hours :)  But maybe you or some else can figure out the correct schema, if not I'll look at it again after work.

 

Share this post


Link to post
Share on other sites

Formerly I made this snippet for personal use. No warranty !  It can work... according on its mood at this moment  :idiot:

$s = FileRead("file.xml")
Msgbox(0,"test", _regex($s))
;ConsoleWrite(_regex($s))

Func _regex($xml)
   Local $indent = ""
   While 1
      $xml = StringRegExpReplace($xml, '(?s)((?<!\t)<(\S+)(?:\sxsi:[^>]+)?>.*?</\2>)', @crlf & $indent & '$1' )
      $xml = StringRegExpReplace($xml, '.*>\K(</[^>]+>)', @crlf & $indent & '$1')
      If @extended = 0 Then Exitloop
      $indent &= @tab
  Wend
  $str = StringRegExpReplace($xml, '\R+', @crlf)
  Return $str
EndFunc

 

Share this post


Link to post
Share on other sites

@mikell

This one has surely never been used before :D

It's for you :muttley:


Click here to see my signature:

Spoiler

Thoughts:

  • I will always thank you for the time you spent for me.
    I'm here to ask, and from your response, I'd like to learn.
    By my knowledge, I can help someone else, and "that someone" could help in turn another, and so on.

/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/

ALWAYS GOOD TO READ:

 

Share this post


Link to post
Share on other sites
Posted (edited)

@Making the zigzag tied it is perhaps better to begin the encounter with the last line ..

 

#include <String.au3>
#include <File.au3>
Global Const $INDENT_SPACES = 3
Local $Xml = FileRead("file.xml"), $sFilePath = @ScriptDir & "\xml_test.xml", $hFileOpen = FileOpen($sFilePath, 2), $Ind = 0
Local $a = StringRegExp(StringRegExpReplace($Xml, '><', ">" & @LF & "<"), '<.*', 3)

For $i = UBound($a) - 1 To 0 Step -1
    If Not StringRegExp($a[$i], "^\<.*\<") Then
        If StringRegExp($a[$i], "^\</") Then
            $a[$i] = _StringRepeat(" ", $Ind * $INDENT_SPACES) & $a[$i]
            $Ind += 1
        Else
            $Ind -= 1
            $a[$i] = _StringRepeat(" ", $Ind * $INDENT_SPACES) & $a[$i]
        EndIf
    Else
        $a[$i] = _StringRepeat(" ", $Ind * $INDENT_SPACES) & $a[$i]
    EndIf
Next

_FileWriteFromArray($hFileOpen, $a)
FileClose($hFileOpen)
Run("notepad.exe " & $sFilePath)

Deye

Edited by Deye
@Borrowing bits from here and there .. vice versa :)

Share this post


Link to post
Share on other sites
Posted (edited)

The non-regexp way :

#include <String.au3>

Global Const $INDENT_SPACES = 3
Local $s = StringStripCR(FileRead ("File.xml"))
Local $a = StringSplit(StringReplace ($s, "><", ">" & @LF & "<"), @LF)
Local $Ind = -1
For $i = 1 to $a[0]
  if StringLeft ($a[$i],2) = "</" Then $Ind -= 1
  ConsoleWrite (_StringRepeat(" ",$Ind*$INDENT_SPACES) & $a[$i] & @CRLF)
  if not StringInStr ($a[$i],"</") Then $Ind += 1
Next

 

Edited by Nine

Share this post


Link to post
Share on other sites

Updated My above example to use _StringRepeat() (didn't noticed it before)  borrowed back a few bits from @Nine

  also to ditch the silly consolewrite playing option :frantics:

@Nine not that it makes much difference but if you look closely, The warping with your example isn't  the same ..
what made my example longer @ picking  And just posted the first thing that worked for me

Deye

 

Share this post


Link to post
Share on other sites

Guys, sorry for very late response, we're on our business trip and I just got back to the office today.

Anyways, I tried all your suggested codes and all are working fine, appreciated guys. Thank you so much!😄

@mikell, @Deye and @Nine, thanks guys...👍

 


Programming is "To make it so simple that there are obviously no deficiencies" or "To make it so complicated that there are no obvious deficiencies" by C.A.R. Hoare.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...