我需要读取XML文件,并根据某些条件对其中的某些元素进行注释或取消注释。 文件开头就像这样:
element1
如果我要激活element3
,element5
和<elements>
<element1 atribute="value"/>
<!-- <element2 atribute="value"/> -->
<element3 atribute="value"/>
<!-- <element4 atribute="value"/> -->
<element5 atribute="value"/>
</elements>
,该文件应如下所示:
<!--
换句话说,我正在寻找一种方法来添加或删除符合条件的每个XML行中的-->
fatalError :: (Show a1, Show a) => [Char] -> a -> a1 -> t
fatalError s l c = error ("Error at line " ++ (show l) ++ " column " ++ (show c) ++ ": " ++ s)
个标记。
不幸的是,这种行为是必需的,无法改变。
答案 0 :(得分:5)
我认为阅读评论和取消评论会使这个问题变得复杂。更简单的方法是添加属性,您可以通过该属性激活标记或停用。只要您要求将其标记为真或假,就不需要解决方法。
例如:
<elements>
<!-- <element1 atribute="value"/> -->
<!-- <element2 atribute="value"/> -->
<!-- <element3 atribute="value"/> -->
<!-- <element4 atribute="value"/> -->
<!-- <element5 atribute="value"/> -->
</elements>
可以转化为。
<elements>
<element1 atribute="value" isActive="false"/>
<element2 atribute="value" isActive="false"/>
<element3 atribute="value" isActive="false"/>
<element4 atribute="value" isActive="false"/>
<element5 atribute="value" isActive="false"/>
</elements>
同样,在
之下<?xml version="1.0" encoding="UTF-8"?>
<elements>
<element1 atribute="value"/>
<!--<element2 atribute="value"/>-->
<element3 atribute="value"/>
<!--<element4 atribute="value"/>-->
<element5 atribute="value"/>
</elements>
可以转化为。
<elements>
<element1 atribute="value" isActive="true"/>
<element2 atribute="value" isActive="false"/>
<element3 atribute="value" isActive="true"/>
<element4 atribute="value" isActive="false"/>
<element5 atribute="value" isActive="true"/>
</elements>
这可以是解决此问题的优化方法。现在,您可以使用JAXB并将元素标记为活动或非活动,而不是注释和取消注释。
如果这不会让您的生活更轻松,那么总是使用正则表达式,xslt等进行解决方法。
答案 1 :(得分:4)
对于这种需求,我会明确建议XSLT
,因为它已经创建了XML transformation
和XSLT
来转换XML
内容。
然后我会使用一个样式表的模板,这个样式表应该像这样用作String格式:
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>
<xsl:template match='/'>
<elements>
<xsl:apply-templates select="elements/element1" mode="%s"/>
<xsl:apply-templates select="elements/element2" mode="%s"/>
<xsl:apply-templates select="elements/element3" mode="%s"/>
<xsl:apply-templates select="elements/element4" mode="%s"/>
<xsl:apply-templates select="elements/element5" mode="%s"/>
</elements>
</xsl:template>
<xsl:template match='*' mode='normal'>
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match='*' mode='comment'>
<xsl:text disable-output-escaping="yes"><!--</xsl:text><xsl:copy-of select="."/>--<xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:template>
</xsl:stylesheet>
如您所见,有两种模式:
normal
,则只会复制节点的内容comment
,则会评论其内容如果我们激活element1
,element3
和element5
,我们的样式表的真实内容将是String.format(template, "normal", "comment", "normal", "comment", "normal")
在下面的代码段中,我使用jcabi-xml,因为它非常易于使用,但如果您愿意,可以自由使用其他库,XSLT
是一个标准,因此它仍然可以使用。< / p>
XML first = new XMLDocument(
"<elements>\n" +
" <element1 atribute=\"value\"/>\n" +
" <element2 atribute=\"value\"/>\n" +
" <element3 atribute=\"value\"/>\n" +
" <element4 atribute=\"value\"/>\n" +
" <element5 atribute=\"value\"/>\n" +
"</elements>"
);
String template = "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='2.0'>\n" +
" <xsl:template match='/'>\n" +
" <elements>\n" +
" <xsl:apply-templates select=\"elements/element1\" mode=\"%s\"/>\n" +
" <xsl:apply-templates select=\"elements/element2\" mode=\"%s\"/>\n" +
" <xsl:apply-templates select=\"elements/element3\" mode=\"%s\"/>\n" +
" <xsl:apply-templates select=\"elements/element4\" mode=\"%s\"/>\n" +
" <xsl:apply-templates select=\"elements/element5\" mode=\"%s\"/>\n" +
" </elements>\n" +
" </xsl:template>\n" +
" <xsl:template match='*' mode='normal'>\n" +
" <xsl:copy-of select=\".\"/>\n" +
" </xsl:template>\n" +
" <xsl:template match='*' mode='comment'>\n" +
" <xsl:text disable-output-escaping=\"yes\"><!--</xsl:text><xsl:copy-of select=\".\"/>--<xsl:text disable-output-escaping=\"yes\">></xsl:text>\n" +
" </xsl:template>\n" +
"</xsl:stylesheet>";
XML second = new XSLDocument(
String.format(template, "normal", "comment", "normal", "comment", "normal")
).transform(first);
System.out.println(second.toString());
<强>输出:强>
<?xml version="1.0" encoding="UTF-8"?>
<elements>
<element1 atribute="value"/>
<!--<element2 atribute="value"/>-->
<element3 atribute="value"/>
<!--<element4 atribute="value"/>-->
<element5 atribute="value"/>
</elements>
NB:为了便于阅读,我格式化了输出
答案 2 :(得分:3)
我不认为纯粹使用JAXB
是可以实现的。这是一种使用STAX API
实现的方法。我使用了类似的实现,我需要操作XML comments
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader reader =factory.createXMLEventReader(new FileReader("input.xml"));
XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(new FileWriter("out.xml"));
String toggleMe = "element2";
String regEx = "<!--(.*)-->";
while(reader.hasNext()) {
XMLEvent event = reader.nextEvent();
if(event.getEventType() == XMLStreamConstants.COMMENT) {
if(event.toString().contains(toggleMe)) {
String xmlElement = event.toString().replaceAll(regEx, "$1");
XMLEventReader elementReader = factory.createFilteredReader(factory.createXMLEventReader(new StringReader(xmlElement)), new DocElementEventFilter());
while(elementReader.hasNext()) {
writer.add(elementReader.nextEvent());
}
}else {
writer.add(event);
}
} else {
writer.add(event);
}
}
writer.flush();
writer.close();
reader.close();
这非常特定于您提供的示例xml,并且当前支持切换一个元素。您可以扩展它以切换多个元素。
以上代码也使用以下事件过滤器
class DocElementEventFilter implements EventFilter {
@Override
public boolean accept(XMLEvent event) {
return !(event.isStartDocument() || event.isEndDocument());
}
}
希望这会对你有所帮助。
答案 3 :(得分:2)
评论是一种特殊类型的节点。你不能切换&#34;切换&#34;从/到评论/未注释的状态。我在这里看到至少太多的可能性,只有在没有JAXB的情况下:
with setIgnoringComments(false)
)不要犹豫,询问您是否需要更详细的答案。您应该很容易找到每个步骤的大量文档。
您也可以使用XSLT,正如@Xavier在评论中指出的那样。这里的问题是纯匹配和替换会将评论的内容输出为未转义的文本,并且不会将其识别为真实的XML数据。我可以使用撒克逊来避开这种情况,例如:
<xsl:template match="comment()[contains(., 'your conditional match')]">
<xsl:variable name="comment" select="saxon:parse(.)" as="document-node()"/>
<xsl:copy-of select="$comment"/>
</xsl:template>