2011-02-04 10 views
4

QTextEditエディタで生成されたHTMLを実際のWebページで使用するために少しフレンドリーに変換したいと思っています。残念ながら、QTextEdit APIの一部であるHTMLジェネレータはパブリックではなく、変更することはできません。XQueryでHTMLを変換する

qt-interestメーリングリストに関する簡単な議論で、誰かがQtXmlPatternsモジュールを介してXQueryを使って言及しました。

を醜いHTMLエディタ出力の例については、それは、太字テキストの<span style=" font-weight:600">を使用して大胆ため<span style=" font-weight:600; text-decoration: underline">とテキストに下線を引くなどここのサンプルです:

<html> 
    <head> 
    </head> 
    <body style=" font-family:'Lucida Grande'; font-size:14pt; font-weight:400; font-style:normal;"> 
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text</p> 
    <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> 
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text <span style=" font-weight:600;">bold text</span></p> 
    <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"></p> 
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text <span style=" font-style:italic;">italics text</span></p> 
    <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-style:italic;"></p> 
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text <span style=" text-decoration: underline;">underline text</span></p> 
    <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> 
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text <span style=" font-weight:600; text-decoration: underline;">bold underline text</span></p> 
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text <span style=" font-weight:600;">bold text </span><span style=" font-weight:600; text-decoration: underline;">bold underline text</span></p> 
    </body> 
</html> 

私はこれを変換したいのですがどのようなこの行に沿って何かがあります。

<body> 
    <p>plain text</p> 
    <p/> 
    <p>plain text <b>bold text</b></p> 
    <p/> 
    <p>plain text <em>italics text</em></p> 
    <p/> 
    <p>plain text <u>underline text</u></p> 
    <p/> 
    <p>plain text <b>bold text <u>bold underline text</u></b></p> 
</body> 

私は、必要な場所の90%近くを得ています。各<span>スタイルメンバーが斜体、太字、または下線のいずれかの属性しか持たない最初の4つを正しく変換できます。スパンスタイルに複数の属性がある場合、私は問題を抱えています。たとえば、スパンスタイルにfont-weight:600text-decoration: underlineの両方が含まれているとします。

は、ここで私はこれまで持っている私のXQueryコードです:

ALMOST正しい結果を与える
declare function local:process_span_data($node as node()) 
{ 
    for $n in $node 
    return (
     for $attr in $n/@style 
     return (
      if(contains($attr, 'font-weight:600')) then (
       <b>{data($n)}</b> 
      ) 
      else if(contains($attr, 'text-decoration: underline')) then (
       <u>{data($n)}</u> 
      ) 
      else if (contains($attr, 'font-style:italic')) then (
       <em>{data($n)}</em> 
      ) 
      else (
       data($n) 
      ) 
     ) 
    ) 
}; 

declare function local:process_p_data($data as node()+) 
{ 
    for $d in $data 
    return (
     if ($d instance of text()) then $d 
     else local:process_span_data($d) 
    ) 
}; 

let $doc := doc('myfile.html') 

for $body in $doc/html/body 
return 
    <body> 
    { 
    for $p in $body/p 
    return (
     if (contains($p/@style, '-qt-paragraph-type:empty;')) then (
      <p /> 
     ) 
     else (
      if (count($p/*) = 0) then (
       <p>{data($p)}</p> 
      ) 
      else (
       <p> 
       {for $data in $p/node() 
       return local:process_p_data($data)} 
       </p> 
      ) 
     ) 
    ) 
    }</body> 

<body> 
    <p>plain text</p> 
    <p/> 
    <p>plain text <b>bold text</b> 
    </p> 
    <p/> 
    <p>plain text <em>italics text</em> 
    </p> 
    <p/> 
    <p>plain text <u>underline text</u> 
    </p> 
    <p/> 
    <p>plain text <b>bold underline text</b> 
    </p> 
    <p>plain text <b>bold text </b> 
     <b>bold underline text</b> <!-- NOT UNDERLINED!! --> 
    </p> 
</body> 

誰もが自分の所望の出力を達成するための正しい方向に私を指すことができます? XQuery n00bから事前に感謝します!

+0

私は、XQueryが何であるか分からないが、問題は、一度コードかどうかをチェックするということです要素はスタイルを持ち、値を返します。要素のすべての値をチェックしてからそれを返す必要があります。 – JCOC611

+0

これにXSLTを使用しないことを決定するには、むしろマゾヒスティックでなければなりません。 XSLTソリューションは些細なことであり、書き込むのに2分しかかかりません。 :) –

+0

XSLTについて何も知らない人のために書くのにどれくらい時間がかかりますか? –

答えて

1

あなたのアプローチは正しいですが、XQuery変換ロジックは少し機能しないパラダイムアプローチです。

これをチェックしてください。

xquery version '1.0-ml'; 
declare namespace mittai = "mittai"; 

declare function mittai:parse-thru($n as node()) 
{ 
    for $z in $n/node() 
    return mittai:dispatch($z) 
}; 

declare function mittai:dispatch($n as node()) 
{ 
    typeswitch($n) 
     case text() return $n 
     case element(p) return element{ fn:node-name($n) } {mittai:parse-thru($n)} 
     case element(span) return element{ fn:node-name($n) } {mittai:parse-thru($n)}  
     case element(body) return element{ fn:node-name($n) } {mittai:parse-thru($n)}  
     default return element{ fn:node-name($n) } {$n/@*, mittai:parse-thru($n)} 

}; 

let $d := doc('myfile.html') 
return <html> {mittai:parse-thru($d)} </html> 
+0

ありがとう、私はこれをチェックします。私のアプローチは間違いなく非機能的なアプローチであることに同意します。私は機能的なパラダイムで多くの経験がありません。主に不可欠です。 –

+0

これは良いですが、それは古典的なアイデンティティの変換ではありません... –

+0

@アレヤンドロ - あなたは私たちが完全に感じる識別変換のためのいくつかのポインタを提供してください。 – kadalamittai

0

(共通のアイデンティティ機能を使用して)このXQueryの:

declare variable $Prop as element()* := 
     (<prop name="em">font-style:italic</prop>, 
     <prop name="strong">font-weight:600</prop>, 
     <prop name="u">text-decoration:underline</prop>); 

declare function local:copy($element as element()) { 
    element {node-name($element)} 
    {$element/@*, 
    for $child in $element/node() 
     return if ($child instance of element()) 
      then local:match($child) 
      else $child 
    } 
}; 
declare function local:match($element as element()) { 
    if ($element/self::span[@style]) 
    then local:replace($element) 
    else local:copy($element) 
}; 
declare function local:replace($element as element()) { 
    let $prop := local:parse($element/@style) 
    let $no-match := $prop[not(.=$Prop)] 
    return element {node-name($element)} 
      {$element/@* except $element/@style, 
      if (exists($no-match)) 
      then attribute style 
        {string-join($no-match,';')} 
      else(), 
      local:nested($Prop[.=$prop]/@name,$element)} 
}; 
declare function local:parse($string as xs:string) { 
    for $property in tokenize($string,';')[.] 
    return 
    <prop>{ 
     replace(normalize-space($property),'()?:()?',':') 
    }</prop> 
}; 
declare function local:nested($names as xs:string*, 
           $element as element()) { 
    if (exists($names)) 
    then element {$names[1]} 
     {local:nested($names[position()>1],$element)} 
    else for $child in $element/node() 
     return if ($child instance of element()) 
      then local:match($child) 
      else $child 
}; 
local:match(*) 

出力:

<html> 
    <head> </head> 
    <body style=" font-family:'Lucida Grande'; font-size:14pt; font-weight:400; font-style:normal;"> 
     <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text</p> 
     <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"/> 
     <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text 
      <span> 
       <strong>bold text</strong> 
      </span> 
     </p> 
     <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"/> 
     <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text 
      <span> 
       <em>italics text</em> 
      </span> 
     </p> 
     <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-style:italic;"/> 
     <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text 
      <span> 
       <u>underline text</u> 
      </span> 
     </p> 
     <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"/> 
     <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text 
      <span> 
       <strong> 
        <u>bold underline text</u> 
       </strong> 
      </span> 
     </p> 
     <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">plain text 
      <span> 
       <strong>bold text </strong> 
      </span> 
      <span> 
       <strong> 
        <u>bold underline text</u> 
       </strong> 
      </span> 
     </p> 
    </body> 
</html>