【问题标题】:handling HTML data in Oracle query在 Oracle 查询中处理 HTML 数据
【发布时间】:2016-02-17 12:45:09
【问题描述】:

我有一个包含 ID、TEXT 等列的表 这里的 TEXT 是包含 HTML FORMAT 数据的 clob 列

从 ID=1000 的表格中选择 ID、文本

我得到如下文本列的输出

<p>NAME:&nbsp;&nbsp;XXX<br />Company Name: &nbsp;YYYYY<br />Location:&nbsp;ZZZ, 22 Z1Z1Z1, Z2Z2Z2,Z3Z3Z3, 0000024, IND<br />Type:&nbsp;PrePA<br />
Team:&nbsp;Team1, Dues tamble <br />Date:&nbsp;January 25 &ndash; 26, 2016<br />Rating: &nbsp;Tr 2<br />Number:&nbsp;8554342</p>
<p><u>Observ: <br /></u>There were (6) major and (2) minor .<br />&nbsp;<br />MAJOR</p><ul>    <li>Sample Text_1.</li>    <li>Sample Text_2.</li>    
<li>Sample Text_33.</li>    <li>Sample Text_4.</li>    <li>Sample Text_5.</li></ul><p>MINOR</p><ul>    <li>Sample Text_7</li>    
<li>Sample Text_8<br />    &nbsp;</li></ul><p><b> Background</b><br />&nbsp;</p>

我需要像下面这样的输出

NAME:  XXX
Company Name:  YYYYY
Location: ZZZ, 22 Z1Z1Z1, Z2Z2Z2,Z3Z3Z3, 0000024, IND
Type: PrePA
Team: Team1, Dues tamble 
Date: January 25 – 26, 2016
Rating:  Tr 2
Number: 8554342

Observ: 
There were (6) major and (2) minor .

MAJOR

Sample Text_1. 
Sample Text_2. 
Sample Text_33. 
Sample Text_4. 
Sample Text_5.
MINOR

Sample Text_7 
Sample Text_8

Background

这意味着查询应该处理 HTML 数据,并且应该像上面一样提供准确的数据。

我有一个查询,它处理 somwhat okey 但它没有处理

exactly the HTML tags.
select ID,
trim(regexp_replace (trim
(regexp_replace( TEXT ,'<[^>]+/>|</[^>]+>|<p>',CHR(13)||CHR(10)))
,'<[^>]+>',''))
from TABLE where ID='1000'

实际上,我需要处理数据中的所有 html 标签,而不仅仅是我展示的示例。

【问题讨论】:

    标签: html oracle oracle11g oracle10g


    【解决方案1】:

    搜索“完美”查询可能会失败;浏览器(包括其他地方推荐的文本浏览器)已经花费了数年时间来解决所有问题和边缘情况。

    如果你真的不能使用外部资源,你可以通过 dbms_xmldom 包遍历 DOM。这是一个使用匿名块和您的示例值的演示,它会打印到屏幕上(如果您启用了该功能);但是您可以轻松地将其调整为返回 CLOB 的函数,或者您需要的任何最终结果。

    set serveroutput on
    set define off
    
    declare     
      l_element xmldom.domelement;
      l_document xmldom.domdocument;
      l_text clob;
    
      procedure print_node (p_node xmldom.domnode) is
        l_nodes dbms_xmldom.domnodelist;
      begin
        -- print out any plain text
        if dbms_xmldom.getnodetype(p_node) = 3
            and dbms_xmldom.getnodename(p_node) = '#text' then
          dbms_output.put_line(dbms_xmldom.getnodevalue(p_node));
        end if;
        -- just to match your expected output, add a blank line for p tags
        if dbms_xmldom.getnodetype(p_node) = 1
            and dbms_xmldom.getnodename(p_node) = 'p' then
          dbms_output.new_line;
        end if;
        -- get any child nodes
        l_nodes := dbms_xmldom.getchildnodes(p_node);
        -- process each node in turn, recursively
        for i in 0..dbms_xmldom.getlength(l_nodes) - 1 loop
          print_node(dbms_xmldom.item(l_nodes, i));
        end loop;
      end print_node;
    
    begin           
      l_text := '<p>NAME:&nbsp;&nbsp;XXX<br />Company Name: &nbsp;YYYYY<br />Location:&nbsp;ZZZ, 22 Z1Z1Z1, Z2Z2Z2,Z3Z3Z3, 0000024, IND<br />Type:&nbsp;PrePA<br />Team:&nbsp;Team1, Dues tamble <br />Date:&nbsp;January 25 &ndash; 26, 2016<br />Rating: &nbsp;Tr 2<br />Number:&nbsp;8554342</p>
    <p><u>Observ: <br /></u>There were (6) major and (2) minor .<br />&nbsp;<br />MAJOR</p><ul>    <li>Sample Text_1.</li>    <li>Sample Text_2.</li>    
    <li>Sample Text_33.</li>    <li>Sample Text_4.</li>    <li>Sample Text_5.</li></ul><p>MINOR</p><ul>    <li>Sample Text_7</li>    
    <li>Sample Text_8<br />    &nbsp;</li></ul><p><b> Background</b><br />&nbsp;</p>'; 
    
      -- wrap the fragment in a root node so it parses, and run through
      -- utl_i18n.unescape_reference to get rid of &nbsp; etc.
      l_document := dbms_xmldom.newdomdocument('<html>'
        || utl_i18n.unescape_reference(l_text) || '</html>');
      -- get the root element (which is now the added html)
      l_element := dbms_xmldom.getdocumentelement(l_document);
      -- call the recursive procedure to process this node
      print_node(dbms_xmldom.makenode(l_element));
    end;
    /
    

    产生:

    NAME:  XXX
    Company Name:  YYYYY
    Location: ZZZ, 22 Z1Z1Z1, Z2Z2Z2,Z3Z3Z3, 0000024, IND
    Type: PrePA
    Team: Team1, Dues tamble 
    Date: January 25 – 26, 2016
    Rating:  Tr 2
    Number: 8554342
    
    Observ: 
    There were (6) major and (2) minor .
     
    MAJOR
    Sample Text_1.
    Sample Text_2.
    Sample Text_33.
    Sample Text_4.
    Sample Text_5.
    
    MINOR
    Sample Text_7
    Sample Text_8
         
    
     Background
     
    

    【讨论】:

    • 很好的例子,但第一行 +1。尝试编写正则表达式来解析 HTML 需要一个指向顶级帖子之一的强制性链接 - stackoverflow.com/a/1732454/4499055
    • 对不起,我的评论实际上是针对 OP 的。看来他想要一个基于问题中示例 sql 的正则表达式查询以及另一个回复中的 cmets。我真的很喜欢你为此使用 dbms_xmldom 的想法。
    【解决方案2】:

    创建一个(简单的)HTML 解析器。

    Oracle 设置

    SET DEFINE OFF;
    
    CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED HTMLTOTEXT AS
    import java.io.IOException;
    import java.io.StringReader;
    import java.util.HashMap;
    import javax.swing.text.MutableAttributeSet;
    import javax.swing.text.html.HTML.Tag;
    import javax.swing.text.html.HTMLEditorKit.ParserCallback;
    import javax.swing.text.html.parser.ParserDelegator;
    
    public class HTMLToText {
        private HTMLToText(){};
    
        private static class TextStripper extends ParserCallback {
            private final StringBuffer buffer = new StringBuffer();
    
            private static final HashMap<Tag, String> START_TAGS = new HashMap<Tag, String>();
            private static final HashMap<Tag, String> END_TAGS = new HashMap<Tag, String>();
            private static final String NEWLINE = "\r\n";
    
            static {
                START_TAGS.put(Tag.BR,    NEWLINE);
                START_TAGS.put(Tag.P,     NEWLINE);
                START_TAGS.put(Tag.LI,    NEWLINE);
                START_TAGS.put(Tag.DT,    NEWLINE);
                START_TAGS.put(Tag.DL,    NEWLINE);
                START_TAGS.put(Tag.OL,    NEWLINE);
                START_TAGS.put(Tag.UL,    NEWLINE);
                START_TAGS.put(Tag.TR,    NEWLINE);
                START_TAGS.put(Tag.TD,    "\t");
                START_TAGS.put(Tag.TH,    "\t");
    
                END_TAGS.put(Tag.P,     NEWLINE);
                END_TAGS.put(Tag.LI,    NEWLINE);
                END_TAGS.put(Tag.DD,    NEWLINE);
                END_TAGS.put(Tag.DL,    NEWLINE);
                END_TAGS.put(Tag.OL,    NEWLINE);
                END_TAGS.put(Tag.UL,    NEWLINE);
                END_TAGS.put(Tag.TR,    NEWLINE);
            }
    
            private boolean newline = true;
    
            @Override
            public void handleText( final char[] data, final int pos ){
    
                buffer.append(data);
                newline = false;
            }
            @Override
            public void handleStartTag( final Tag tag, final MutableAttributeSet attribute, final int pos ){
                if ( !newline && START_TAGS.containsKey( tag ) )
                {
                    final String value = START_TAGS.get( tag );
                    buffer.append( value );
                    newline = value.equals(NEWLINE);
                }
            }
            @Override
            public void handleEndTag( final Tag tag, final int pos ){
                if ( !newline && END_TAGS.containsKey( tag ) )
                {
                    final String value = END_TAGS.get( tag );
                    buffer.append( value );
                    newline = value.equals(NEWLINE);
                }
            }
            @Override
            public void handleSimpleTag( final Tag tag, final MutableAttributeSet attribute, final int pos ){
                handleStartTag( tag, attribute, pos );
                handleEndTag( tag, pos );
            }
            @Override
            public void handleComment( final char[] data, final int pos ){}
            @Override
            public void handleError( final String errMsg, final int pos ){}
    
            public String getText(){
                return buffer.toString();
            }
        }
    
        private static final ParserDelegator DELEGATOR = new ParserDelegator();
    
        public static String extractText( final String html ) throws IOException{
            TextStripper stripper = new TextStripper();
            DELEGATOR.parse( new StringReader( html ), stripper, true );
            return stripper.getText();
        }
    };
    /
    
    CREATE OR REPLACE FUNCTION HTML_TO_TEXT(
      in_html  IN VARCHAR2
    ) RETURN VARCHAR2
    AS LANGUAGE JAVA NAME 'HTMLToText.extractText( java.lang.String ) return java.lang.String';
    /
    SHOW ERRORS;
    /
    

    查询

    SELECT HTML_TO_TEXT( '<html><body>Text<p>para<br>graph</p><table><tr><th>R1</th><td>C1</td><td>C2</td></tr><tr><th>R2</th><td>C1</td><td>C2</td></tr></table></body></html>' ) FROM DUAL;
    

    输出

    HTML_TO_TEXT('<HTML><BODY>TEXT<P>PARA<BR>GRAPH</P><TABLE><TR><TH>R1</TH><TD>C1</
    --------------------------------------------------------------------------------
    Text                                                                            
    para                                                                            
    graph                                                                           
    R1  C1  C2                                                                          
    R2  C1  C2
    

    【讨论】:

    • 这很好用。但它不接受 CLOB 列。我有 CLOB 作为输入。这段代码需要做哪些修改?
    • 我没有时间测试这个但尝试将最终函数定义的参数和返回类型从VARCHAR2更改为CLOB
    • 我尝试了那些 initla 的东西。但是收到诸如“ORA-00932:不一致的数据类型:期望参数位置 1 处的值可转换为 Java java.lang.String 得到一个 Oracle CLOB”之类的错误。由于我在 Java 方面做得不好,因此无法更改您的代码。
    • 如何实现unescapeHtml(writer, data);在上面的答案中起作用?
    【解决方案3】:

    考虑通过lynx -stdin 运行HTML 以将其呈现为纯文本。 Lynx 是一个用于文本控制台的网络浏览器。

    【讨论】:

    • 其实我需要oracle中的一个查询来处理html标签并产生没有html标签但有html标签含义的输出。
    • 您需要的是可以将 HTML 呈现为文本的东西。可能包括表格、对齐等内容。您需要一个文本浏览器。有没有办法将查询结果通过管道传输到充当过滤器的外部命令中?这样就可以了。
    • 我无法使用 ant 文本浏览器。我需要处理查询本身中的 html 标签。
    • 我想你可以尝试一个尽力而为的解决方案。 Here 是一个处理删除 HTML 标签的问题。
    • 该解决方案并不完美。即使我有比这更好的查询。
    猜你喜欢
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多