# Tagz-5.0.0 -- processing instruction support

**URL:** <https://www.ruby-forum.com/t/tagz-5-0-0-processing-instruction-support/164089>\
**Category:** Ruby\
**Created:** [March 27, 2009, 7:09pm UTC](https://www.ruby-forum.com/t/tagz-5-0-0-processing-instruction-support/164089 "2009-03-27T19:09:41Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andrew\_SSTownley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d07c76/32.png) [@Andrew\_SSTownley](https://www.ruby-forum.com/u/Andrew_SSTownley)\
**Post date:** [March 27, 2009, 7:09pm UTC](https://www.ruby-forum.com/t/tagz-5-0-0-processing-instruction-support/164089/1 "2009-03-27T19:09:41Z")

</div>

Hi Ara,

I’m sure you’re sick of me by now, but I’ve added processing instruction  
support to tagz. It may not suit your style, but I’ve tried to keep it  
in the spirit of the library.

excalibur$ diff  
-u /var/lib/gems/1.8/gems/tagz-5.0.0/lib/tagz.rb /tmp/tagz.rb  
— /var/lib/gems/1.8/gems/tagz-5.0.0/lib/tagz.rb 2009-03-24  
11:58:05.000000000 +0000  
+++ /tmp/tagz.rb 2009-03-27 18:01:11.000000000 +0000  
@@ -15,27 +15,7 @@

# open\_tag

# 

```
 def tagz__ name, *argv, &block

```

- 

```
 options = argv.last.is_a?(Hash) ? argv.pop : {}

```

- 

```
 content = argv

```

- 
- 

```
 unless options.empty?

```

- 

```
   attributes = ' ' <<

```

- 

```
     options.map do |key, value|

```

- 

```
       key = XChar.escape key.to_s

```

- 

```
       value = XChar.escape value.to_s

```

- 

```
       if value =~ %r/"/

```

- 

```
         raise ArgumentError, value if value =~ %r/'/

```

- 

```
         value = "'#{ value }'"

```

- 

```
       else

```

- 

```
         raise ArgumentError, value if value =~ %r/"/

```

- 

```
         value = "\"#{ value }\""

```

- 

```
       end

```

- 

```
       [key, value].join('=')

```

- 

```
     end.join(' ')

```

- 

```
 else

```

- 

```
   attributes = ''

```

- 

```
 end

```

- 

- 

```
 attributes, content = process_attributes *argv, &block
 tagz.concat "<#{ name }#{ attributes }>"

 if content.empty?

```

@@ -68,6 +48,13 @@  
tagz.concat “\</#{ tag }\>”  
end

- 
# processing instruction
- 
# 
- def tagz\_? name, \*argv, &block
- 

```
 attributes, content = process_attributes *argv, &block

```

- 

```
 tagz.concat "<?#{ name }#{ attributes }?>"

```

- end
- 
# access tagz doc and enclose tagz operations

# 
def tagz document = nil, &block  
@@ -94,6 +81,8 @@  
def method\_missing m, \*a, &b  
strategy =  
case m.to\_s
- 

```
     when %r/^(.*[^?])_\?$/o

```

- 

```
       :processing_instruction
     when %r/^(.*[^_])_(!)?$/o
       :open_tag
     when %r/^_([^_].*)$/o

```

@@ -119,6 +108,9 @@  
m, bang = $1, $2  
b ||= lambda{} if bang  
tagz{ tagz\_\_(m, \*a, &b) }

- 

```
   when :processing_instruction

```

- 

```
     m = $1

```

- 

```
     tagz{ tagz_?(m, *a, &b) }
   when :close_tag
     m = $1
     tagz{ __tagz(m, *a, &b) }

```

@@ -135,6 +127,33 @@  
end  
end

- def process\_attributes \*argv, &block
- 

```
 options = argv.last.is_a?(Hash) ? argv.pop : {}

```

- 

```
 content = argv

```

- 
- 

```
 attributes = nil

```

- 
- 

```
 unless options.empty?

```

- 

```
   attributes = ' ' <<

```

- 

```
     options.map do |key, value|

```

- 

```
       key = XChar.escape key.to_s

```

- 

```
       value = XChar.escape value.to_s

```

- 

```
       if value =~ %r/"/

```

- 

```
         raise ArgumentError, value if value =~ %r/'/

```

- 

```
         value = "'#{ value }'"

```

- 

```
       else

```

- 

```
         raise ArgumentError, value if value =~ %r/"/

```

- 

```
         value = "\"#{ value }\""

```

- 

```
       end

```

- 

```
       [key, value].join('=')

```

- 

```
     end.join(' ')

```

- 

```
 else

```

- 

```
   attributes = ''

```

- 

```
 end

```

- 
- 

```
 [attributes, content]

```

- end
- class Document \< ::String  
def Document.for other  
Document === other ? other : Document.new(other.to\_s)

excalibur$ cat c.rb  
require ‘tagz’  
include Tagz.globally

doc =  
Tagz {  
xml\_?(:version =\> “1.0”)  
mypi\_?(:arg1 =\> “foo”)  
tagz\_?(“xml-stylesheet”, :href =\> “classic.xsl”, :type =\>  
“text/xml”)  
test\_!  
}

puts doc

excalibur$ ruby c.rb

\<?xml version="1.0"?\>\<?mypi arg1="foo"?\>\<?xml-stylesheet type="text/xml"

href=“classic.xsl”?\>

---

<div class="post-metadata">

**Author:** ![Andrew\_SSTownley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/d07c76/32.png) [@Andrew\_SSTownley](https://www.ruby-forum.com/u/Andrew_SSTownley)\
**Post date:** [March 29, 2009, 1:27am UTC](https://www.ruby-forum.com/t/tagz-5-0-0-processing-instruction-support/164089/2 "2009-03-29T01:27:03Z")

</div>

On Sat, 2009-03-28 at 03:05 +0900, Andrew S. Townley wrote:

> +++ /tmp/tagz.rb 2009-03-27 18:01:11.000000000 +0000  
> Hi Ara,

I was wondering if you might be able to help me. It seems that by  
moving the attribute processing into a separate method, I’ve screwed up  
the scope handling. The patch does indeed deliver processing  
instructions and works fine in the “happy day” path, but if you use any  
kind of conditionals inside an element block, it seems to go haywire.

i.e.:  
$ cat a.rb  
#require ‘rubygems’  
require ‘tagz’

include Tagz.globally

def makeelt  
container\_{  
element\_ {  
child1\_ “hello world”  
}  
arr = []  
if arr.length \> 0  
element2\_ {  
child2\_ “some child”  
}  
end  
}  
end

puts Tagz {  
list\_{  
2.times do  
makeelt  
end  
}  
}

With the patch applied, it gives the following bogus markup:  
hello  
world\</element/\>hello  
world\</element/\>  
^^^^^^^^^^^

With your version, it works as expected, so obviously the patch is  
busted.

Clearly, I don’t quite understand what’s going on enough to know why  
what I changed would cause this sort of behavior. Would you have any  
ideas?

The PI support is a bit of syntax sugar that will be handy for  
generating some of the XML that I need to generate, but I can get by  
with the vanilla one for now.

Still, I’d like to understand why the behavior occurs. If you or anyone  
else has an idea, I’d love to hear it.

If you add an element to the array, it works as expected, so the  
conditional is certainly the key somehow…

$ ruby a.rb | tidy -xml -i  
No warnings or errors were found.

 hello world some child hello world some child 

Other than that, I have to say that I’ve found Tagz absolutely fantastic  
to work with. I’m in the process of converting some of my code to use  
it instead of using string concatenation & hand-coded elements for  
building XML, and it just makes sense.

Brilliant stuff!

Cheers,

ast
