是否可以将 XML-Elements 与 SAX(coremedia CAE 过滤器)合并
Is it possible to merge XML-Elements with SAX (coremedia CAE filter)
给出的是:
一个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-tag
、close-a-tag
)并使用
#characters
我可以提取标签之间的文本。
我的问题是:
我可以创建上述转换(可能吗)?
我的问题是:
- 我可以提取缩写文本和解释文本
- 我可以在最后一个 span-Tag 上调用#startElement
- 但我无法创建标签的内容(在本例中为文本 'ABG')
答案是是有可能!
主要argument/hint你可以从这里得到Whosebug-link
这是必须要做的事情:
- 你必须记住 sax 解析器所在的 span-tag 状态("class=abbreviation" 或 "class=explanation")
- 你必须提取标签的内容(这可以用
#character
方法完成)
- 当您知道 sax 解析器的状态和内容时,您可以创建一个新的
abbr
-tag
- 所有其他标签,必须不加任何修改地接受
为了完整起见,这里是 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(...)
开始元素(...)
此处存储 sax-parser 所在标记的状态(更详细:存储打开哪个 span-tag("class=abbreviation" 或 "class=explanation")的状态。
isAbbreviation
对于带有 "class=abbreviation" 的打开的 span-tag
isExplanation
对于带有 "class=explanation" 的打开的 span-tag
你只存储状态。提到的 span-tags 不会是 processed/filtered (结果是,它们将被删除)。每个其他标签都经过处理而没有过滤,它们将在没有修改的情况下应用(即 else
-block)。
endElement(...)
在这里你只想处理除了(提到的span-tags)之外的每个标签。所有这些标签都没有修改地应用(else
-block)。如果 sax 解析器位于封闭的 span-tag(带有 "class=abbreviation" 或 "class=explanation"),您什么都不做(除了存储状态)
字符数(...)
在这个方法中,魔术(使用解析器创建标签)发生了。取决于州:
- Sax 解析器位于带有 "class=explanation" 的 span-tag 中(这意味着之前传递了一个带 "class=abbreviation" 的开放 span-tag)--> branch
(isAbbreviation && isExplanation)
- Sax解析器位于第一个span-tag(带有"class=abbreviation"的span-tag)--> branch (
isAbbreviation && !isExplanation
)
- 您在任何其他标签中找到的所有其他字符 --> 分支
else
状态 3。
只需复制您找到的文本
状态 2。
使用"class=abbreviation"提取span-tag的内容供以后使用
状态 3。
- 使用"class=explanation"提取span-tag的内容
- 为
abbr
-标签 (title=....
) 创建属性
- 写入新的
abbr
-tag(而不是两个 span-tags)
- 设置状态
给出的是:
一个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-tag
、close-a-tag
)并使用
#characters
我可以提取标签之间的文本。
我的问题是:
我可以创建上述转换(可能吗)?
我的问题是:
- 我可以提取缩写文本和解释文本
- 我可以在最后一个 span-Tag 上调用#startElement
- 但我无法创建标签的内容(在本例中为文本 'ABG')
答案是是有可能!
主要argument/hint你可以从这里得到Whosebug-link
这是必须要做的事情:
- 你必须记住 sax 解析器所在的 span-tag 状态("class=abbreviation" 或 "class=explanation")
- 你必须提取标签的内容(这可以用
#character
方法完成) - 当您知道 sax 解析器的状态和内容时,您可以创建一个新的
abbr
-tag - 所有其他标签,必须不加任何修改地接受
为了完整起见,这里是 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(...)
开始元素(...)
此处存储 sax-parser 所在标记的状态(更详细:存储打开哪个 span-tag("class=abbreviation" 或 "class=explanation")的状态。
isAbbreviation
对于带有 "class=abbreviation" 的打开的 span-tag
isExplanation
对于带有 "class=explanation" 的打开的 span-tag
你只存储状态。提到的 span-tags 不会是 processed/filtered (结果是,它们将被删除)。每个其他标签都经过处理而没有过滤,它们将在没有修改的情况下应用(即 else
-block)。
endElement(...)
在这里你只想处理除了(提到的span-tags)之外的每个标签。所有这些标签都没有修改地应用(else
-block)。如果 sax 解析器位于封闭的 span-tag(带有 "class=abbreviation" 或 "class=explanation"),您什么都不做(除了存储状态)
字符数(...)
在这个方法中,魔术(使用解析器创建标签)发生了。取决于州:
- Sax 解析器位于带有 "class=explanation" 的 span-tag 中(这意味着之前传递了一个带 "class=abbreviation" 的开放 span-tag)--> branch
(isAbbreviation && isExplanation)
- Sax解析器位于第一个span-tag(带有"class=abbreviation"的span-tag)--> branch (
isAbbreviation && !isExplanation
) - 您在任何其他标签中找到的所有其他字符 --> 分支
else
状态 3。
只需复制您找到的文本
状态 2。
使用"class=abbreviation"提取span-tag的内容供以后使用
状态 3。
- 使用"class=explanation"提取span-tag的内容
- 为
abbr
-标签 (title=....
) 创建属性 - 写入新的
abbr
-tag(而不是两个 span-tags) - 设置状态