2
votes

I have an XML document that I would like to convert to HTML. I am using Xquery with Oxygen parser for this.

This is the xml:

<?xml version="1.0" encoding="UTF-8"?>
<?oxygen RNGSchema="file:textbook.rnc" type="compact"?>
<books xmlns="books">

    <book ISBN="i0321165810" publishername="OReilly">
        <title>XPath</title>
        <author>
            <name>
                <fname>Priscilla</fname>
                <lname>Warnley</lname>
            </name>
            <address>
                <street_address>Hill Park<street_address>
                <zip>90210</zip>
                <state>california</state>
            </address>
            <phone>00000000</phone>
            <e-mail>[email protected]</e-mail>
        </author>
        <year>2007</year>
        <field>Databases</field>
        <TOC>
            <component>
                <type>Part</type>
                <title>Xpath</title>
                <component>
                    <title>Chapter... A tour of xquery</title>
                    <pages>3</pages>
                    <component>
                        <title>Introductions</title>
                    </component>
                    <component>
                        <title>Getting started</title>
                    </component>
                </component>
            </component>
        </TOC>
    </book>

    <publisher publishername="OReilly">
        <web-site>www.oreilly.com</web-site>
        <address>
            <street_address>hill park</street_address>
            <zip>90210</zip>
            <state>california</state>
        </address>
        <phone>400400400</phone>
        <e-mail>[email protected]</e-mail>
        <contact>
            <field>Databases</field>
            <name>
                <fname>Anna</fname>
                <lname>Smith</lname>
            </name>
        </contact>
    </publisher>
</books>

I first do this Xquery query:

declare default element namespace "books";
<html>
<head> 
<title>Table of contents</title>
</head>
<body>
<b>Table of contents</b>
<hr/>
{   for $i in //book[@ISBN='i0321165810']/TOC
    return $i
}
</body>
</html>

based on my xml document get these results:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="Books">
   <head>
      <title>Table of content</title>
   </head>
   <body>
      <b>TOC</b>
  <hr/>
      <TOC>
            <component> 
                <type>Part</type>
                <title>Foundations</title>
                <component>
                    <title>Chapter... A tour of xquery</title>
                    <pages>3</pages>
                    <component>
                        <title>Introductions</title>
                    </component>
                    <component>
                        <title>Getting started</title>
                    </component>
                </component>
            </component>
        </TOC>
   </body>
</html>

What I would like to do now is replace the component tag with a pre tag (using spaces for indentation), the title tag with an italics tag and the pages tag with a bold tag (basically use HTML tags instead of XML tags, so the document can be viewed in a web browser). I tried to use the replace function, but I could not get it to work.

Could someone please help?

2
Just curious...why are you using XQuery instead of XSLT?Daniel Haley
Tomalak: I should have written "pre tag" (with spaces), not "tab tag" (which is non-existing in HTML). Thanks for noticing. DevNull: The university class I'm taking is requiring we learn XQuery. It's a course is about database technology, so I guess that's why. It seems that XSLT is more widely used.Jea
@Jea - That is a very good reason. :-)Daniel Haley
@Jea: If you provide your source XML document, then many people will be able to give an answer -- not like now, when we all have (and hate) to guess.Dimitre Novatchev
@DimitreNovatchev: Thank you for replying. I have now provided the source XML document.Jea

2 Answers

5
votes

As DevNull noted, this is a task where XSLT would shine. Here's my go at an XQuery solution:

declare default element namespace "http://www.w3.org/1999/xhtml";

declare function local:rename($node) {
  let $old-name := local-name($node)
  let $new-name :=
    switch($old-name)
      case 'component' return 'pre'
      case 'title'     return 'i'
      case 'pages'     return 'b'
      default          return $old-name
  return element { $new-name } {
    $node/@*,
    for $nd in $node/child::node()
    return if($nd instance of element())
      then local:rename($nd)
      else $nd
  }
};

<html>
  <head> 
     <title>Table of contents</title>
  </head>
  <body>
      <b>Table of contents</b>
      <hr/>
      {   for $i in //*:book[@ISBN='i0321165810']/*:TOC/*
          return local:rename($i)
      }
  </body>
</html>

The function local:rename($node) recursively descends into the XML fragment, rebuilding it and substituting element names. It's neither very elegant nor efficient, but it should do the job.

I also changed the default element namespace, as your returned XHTML document was in the books namespace.

3
votes

One straight-forward way (using XQuery Update) looks as follows:

declare default element namespace "books";
<html>
<head> 
<title>Table of contents</title>
</head>
<body>
<b>Table of contents</b>
<hr/> {
  copy $c := //book[@ISBN='i0321165810']/TOC
  modify (
    for $n in $c//component return rename node $n as 'tab',
    for $n in $c//title return rename node $n as 'i',
    for $n in $c//pages return rename node $n as 'b'
  )
  return $c     
}</body>
</html>

Hope this helps, Christian