是否有可能XML的元素合并使用SAX(coremedia CAE过滤器)

问题描述:

假设是:是否有可能XML的元素合并使用SAX(coremedia CAE过滤器)

一个XML结构像

<span class="abbreviation">AGB<span class"explanation">Allgemeine Geschäftsbedingungen</span></span> 

和改造后的结果应该是:

<abbr title="Allgemeine Geschäftsbedingungen">AGB</abbr> 

我知道SAX是一个基于事件的XML解析器,并且使用类似于如下的方法:

  • #startElement(...)
  • #endElement(...)

我可以捕捉事件(如open-a-tagclose-a-tag),并与

  • #characters

我可以提取标签之间的文本。

我的问题是:

我能创造上述转换(有没有可能)?

我的问题是:

  • 我可以提取的缩写文字和文字解释
  • 我可以叫#startElement上的最后一个跨度标签
  • ,但我不能创建的内容标签(在这种情况下文本'ABG')
+1

如果你处理的是非常大的输入 - 太大而不适合内存,或者处理的时间关键处理在纳秒数量的情况下,否则你只会增加复杂性...... – Adam

+0

这听起来像是XSLT的工作。 –

+0

嗯,我必须使用SAX,因为它是一个模块(核心媒体框架的过滤器) – SleepyX667

答案是是的这是可能的!

主要参数/提示你可以从这个*-link

这里得到的是什么必须做:

  1. 你要记住的状态,在此跨度标签SAX解析器位于(“类=缩写”或“类=解释”)
  2. 你必须提取标记的内容(这可以用#character方法来完成)
  3. 当你知道SAX解析器和内容的状态,你可以N新建一个新的abbr -tag
  4. 所有其他标签,有没有任何修饰

为了完整这里加入是coremedia CAE过滤器的源代码:

import com.coremedia.blueprint.cae.richtext.filter.FilterFactory; 
import com.coremedia.xml.Filter; 
import org.apache.commons.lang3.StringUtils; 
import org.xml.sax.Attributes; 
import org.xml.sax.SAXException; 
import org.xml.sax.helpers.AttributesImpl; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

public class GlossaryFilter extends Filter implements FilterFactory { 
    private static final String SPAN = "span"; 
    private static final String CLASS = "class"; 

    private boolean isAbbreviation = false; 
    private boolean isExplanation = false; 
    private String abbreviation; 
    private String currentUri; 
    private boolean spanExplanationClose = false; 
    private boolean spanAbbreviationClose = false; 

    @Override 
    public Filter getInstance(final HttpServletRequest request, final HttpServletResponse response) { 
    return new GlossaryFilter(); 
    } 

    @Override 
    public void startElement(final String uri, final String localName, final String qName, 
     final Attributes attributes) throws SAXException { 
    if (isSpanAbbreviationTag(qName, attributes)) { 
     isAbbreviation = true; 
    } else if (isSpanExplanationTag(qName, attributes)) { 
     isExplanation = true; 
     currentUri = uri; 
    } else { 
     super.startElement(uri, localName, qName, attributes); 
    } 
    } 

    private boolean isSpanExplanationTag(final String qName, final Attributes attributes) { 
    //noinspection OverlyComplexBooleanExpression 
    return StringUtils.isNotEmpty(qName) && qName.equalsIgnoreCase(SPAN) && (
     attributes.getLength() > 0) && attributes.getValue(CLASS).equals("explanation"); 
    } 

    private boolean isSpanAbbreviationTag(final String qName, final Attributes attributes) { 
    //noinspection OverlyComplexBooleanExpression 
    return StringUtils.isNotEmpty(qName) && qName.equalsIgnoreCase(SPAN) && (
     attributes.getLength() > 0) && attributes.getValue(CLASS).equals("abbreviation"); 
    } 

    @Override 
    public void endElement(final String uri, final String localName, final String qName) 
     throws SAXException { 
    if (spanExplanationClose) { 
     spanExplanationClose = false; 
    } else if (spanAbbreviationClose) { 
     spanAbbreviationClose = false; 
    } else { 
     super.endElement(uri, localName, qName); 
    } 
    } 

    @Override 
    public void characters(final char[] ch, final int start, final int length) throws SAXException { 
    if (isAbbreviation && isExplanation) { 
     final String explanation = new String(ch, start, length); 
     final AttributesImpl newAttributes = createAttributes(explanation); 
     writeAbbrTag(newAttributes); 
     changeState(); 
    } else if (isAbbreviation && !isExplanation) { 
     abbreviation = new String(ch, start, length); 
    } else { 
     super.characters(ch, start, length); 
    } 
    } 

    private void changeState() { 
    isExplanation = false; 
    isAbbreviation = false; 
    spanExplanationClose = true; 
    spanAbbreviationClose = true; 
    } 

    @SuppressWarnings("TypeMayBeWeakened") 
    private void writeAbbrTag(final AttributesImpl newAttributes) throws SAXException { 
    super.startElement(currentUri, "abbr", "abbr", newAttributes); 
    super.characters(abbreviation.toCharArray(), 0, abbreviation.length()); 
    super.endElement(currentUri, "abbr", "abbr"); 
    } 

    private AttributesImpl createAttributes(final String explanation) { 
    final AttributesImpl newAttributes = new AttributesImpl(); 
    newAttributes.addAttribute(currentUri, "title", "abbr:title", "CDATA", explanation); 
    return newAttributes; 
    } 
} 

有趣的东西是在方法:

  • startElement(...)
  • endElement(...)
  • characters(...)

的startElement(...)

在这里,您存储在其标签上的SAX解析器所在的国家(更详细:您存储的状态,这跨度标签(在“class = abbreviation”或“class = explanation”)被打开。

  • isAbbreviation与“类=简称”
  • isExplanation与“类=的解释”

只储存状态的打开跨度标签打开的跨度标签。提到的span标签不会被处理/过滤(结果是,它们将被删除)。每个其他标签都是在不进行过滤的情况下处理的,它们将不加修改地应用(即else -block)。

的endElement(...)

在这里,你只想要处理除(所提到的跨度标签)的每个标签。所有这些标签都不加修改地应用(else -block)。如果SAX解析器位于一个封闭的跨度标签(与“阶级=缩写”或“类=的解释”),你想要什么都不做(除了店面的状态)

字符(...)

在这个方法中,发生了魔术(用解析器创建一个标签)。根据不同的状态:

  1. SAX解析器位于具有“类=的解释”的跨度标签(这意味着有一个与“阶级=简称”日前通过一个开放的跨度标签) - >分支(isAbbreviation && isExplanation)
  2. SAX解析器位于第一区间标签(跨度标签与“类=简称”) - >分支(isAbbreviation && !isExplanation
  3. 您在任何其他标记找到每一个其它字符 - >分支else

为状态3.

简单复制文本您找到

国有2.

提取与“阶级=简称”跨度标签的内容供以后使用

的状态3

  • 用“class = explanation”解释span标签的内容“
  • 创建为abbr - 标签的属性(title=....
  • 写入新abbr - 标签(而不是两个跨度标签)
  • 集我只使用SAX状态