How do I convert contents of an element to fixed width in Omnimark or XSLT?

I am trying to convert an XML file to a fixed width plain text file. Each line of text can only be 83 characters long. Paragraphs should wrap at character 75, character 76 should always be a space, character 77 is a single digit code indicating which section of content the text comes from, and characters 78 through 83 is a 6-digit document ID. Breaks must occur at or before character 75 and only when there is a space (breaking cannot occur in the middle of a word).

See sample input and output files attached.

This is the Omnimark code I've come up with which has several problems...it doesn't break between words and the output in the "do when" section gives the error "Attempting to write a referent to a stream which does not allow referents." I also have a feeling that if it did output, the section-code would be the same for all sections (taking the last sect-id that was assigned to it).

I'm new to XSLT so I don't know if it could provide a better/cleaner solution.

Thanks!

element para
	local stream contents
	local counter line-length initial {0}
	local counter charcount initial {0}
	set contents to '%c'
	set line-length to 75
	output '%n'
	repeat scan contents
	    match any => char
	    	increment charcount
	    	do when charcount = line-length
	    	     output ' ' || referent 'section-code' || referent 'docid' || '%n'
	    	     set charcount to 0
	    	done
	    	output char
	again

Open in new window

sample-output.txt
sample-input.xml.txt
jay7272Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Geert BormansInformation ArchitectCommented:
Hi Jay7272,

do you have a preference OmniMark vs XSLT?
This is one of the (becoming more rare) use cases where omnimark has some advantage over XSLT (1 at least, not 2)
because it is pretty pattern matching (regular expression) intensive

Do you have access to XSLT2?
If so, I will come up with an XSLT2 solution,
if not, I will try and change your omnimark script

in order to not hit the
"write a referent to a stream which does not allow referents"
you have to open the stream with referents allowed

Is thsi OmniMark5?
And are there more element rules?
0
jay7272Author Commented:
Hi Gertone,

Either is fine...I have access to 5.5 and XSLT2. In trying to get the stream open with referents allowed I get further error messages "trying to use stream which is not fully resolved". There are other element rules but most of them are either "output '%c'" or "suppress". The exception being...which I know doesn't test to see if attribute sect-id actually exists on the parent and it also assumes that the heading will always be less than 76 characters.

Jay7272

element head
	local stream heading
	set heading to '%c'
	set referent 'section-code' to attribute sect-id of parent
	output "%n%76fg(heading)" || referent 'section-code' || referent "docid"

Open in new window

0
Geert BormansInformation ArchitectCommented:
There are some buffer issues in OM 5.5. If you have access to 5.3, that would be better
I am working on an OmniMark solution right now, it is a bit more comfortable I must admit
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

Geert BormansInformation ArchitectCommented:
This comes close I think,
you don't need to use referents, throw in some variables
OmniMark is streaming, use that power, so output everything directly whilst you go
and use the context well (attribute docID of preparent document etc)

This needs some finetuning, a similar logic for the head, maybe throw in some functions or so

My OmniMark is a bit rusty, but I bet you can do that yourself
element #implied
    output "%c"
    
element head
    suppress
 
element para
    local integer lcFullLength initial {75}
    local integer lcCurrentLength initial {0}
    repeat scan "%c"
        match [any except "%_"]+ => pat
            do when lcCurrentLength + length of pat > lcFullLength
                output " " ||* (lcFullLength - lcCurrentLength)
                output " " 
                output attribute sect-id of parent
                output attribute docID of preparent document
                output "%n"
                set lcCurrentLength to length of pat
                output pat
            else
                increment lcCurrentLength by length of pat
                output pat
            done
        match " " when lcFullLength = lcCurrentLength
              output " " 
              output attribute sect-id of parent
              output attribute docID of preparent document
              output "%n"
              set lcCurrentLength to 0
        match " "
            output " "
            increment lcCurrentLength 
    again
    ; for the last line        
    do when lcCurrentLength < lcFullLength
        output " " ||* (lcFullLength - lcCurrentLength)
        output " " 
        output attribute sect-id of parent
        output attribute docID of preparent document
        output "%n"
    done

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jay7272Author Commented:
Thanks Gertone...I've incorporated this into my script and it works great!
0
Geert BormansInformation ArchitectCommented:
welcome
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Languages and Standards

From novice to tech pro — start learning today.