解析嵌套在其他XML值中的XML标记
我被困在开发一个解析大量XML的特定XML解析器。解析嵌套在其他XML值中的XML标记
我的问题是我很困惑如何解析嵌套在其他XML值的XML标签。 我的输入文件看起来像这样。
<main>
<step>
<para>Calculate the values from the pool</para>
</step>
<step>
<para>Use these(<internalRef id ="003" xlink:actuate="onRequest" xlink:show="replace" xlink:href="max003"/>) values finally</para>
</step>
</main>
我能够使用xpath获取第一个步骤标记的值。 我的问题是如何使用xpath获取第二步值,或者更确切地说,如何识别何时在值标签内启动新标签。
对于例如,我的第二个步骤XPath是返回我这样的结果 - 使用这些()值最后
这里作为我的目标是GET-使用这些(max003)值终于
的max003值已经从的xlink采取:HREF
加法 - 我可以通过编写单独的xpath来获取id的各个值,启动和显示。我的问题是我需要得到的XLink后后这些值之前东西,括号内的max003值:HREF值是max003,并将其发送跨线进行显示。 所以我正在寻找一种方法来确定哪里和何时子节点ID已经开始?和一种机制将它塞入圆括号内。
这个XPath表达式的评价:
concat(/*/step[2]/para/text()[1],
/*/step[2]/para/internalRef/@xlink:href,
/*/step[2]/para/text()[2])
上提供的XML文档(纠正为命名空间格式化):
<main xmlns:xlink="Undefined namespace">
<step>
<para>Calculate the values from the pool</para>
</step>
<step>
<para>Use these(<internalRef id ="003" xlink:actuate="onRequest" xlink:show="replace" xlink:href="max003"/>) values finally</para>
</step>
</main>
产生通缉的结果:
Use these(max003) values finally
请注意:您需要使用您的XPath API“注册XLink命名空间”,为了让这个XPath表达式没有一个错误进行评估。
基于XSLT的验证:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="Undefined namespace">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select=
"concat(/*/step[2]/para/text()[1],
/*/step[2]/para/internalRef/@xlink:href,
/*/step[2]/para/text()[2])
"/>
</xsl:template>
</xsl:stylesheet>
当这个变换所提供的XML文档(上文),XPath表达式求值和该评价的结果施加被复制到输出 :
Use these(max003) values finally
如果他的
@predi,是的,XPath 2.0。是的,如果预先知道'para'的所有孩子的数量和确切类型,则使用XPath 1.0。不,使用XPath 1.0,如果'para'的所有孩子的数量和确切类型未提前知道 –
尽可能靠近我可以告诉大家,我认为你的分析器是看你构建一个有点像
step
+- para
+-id
它然后包裹在“文本”的内容一起提取ID节点...
(这纯属猜测)
UPDATE
如果我走纯粹节点T稀土元素(列出每个孩子)这就是我得到
main
step
para
#text - Calculate the values from the pool
step
para
#text - Use these(
id
#text -) values finally
这意味着,“ID”,是“对”
的孩子你不能单独使用XPath的事情。你有什么混合内容XML,这意味着一个元素可能包含文本值和子元素。您只能使用XPath一次引用其中的一个,并且您也不能只从多个XPath表达式中获取您的内容,因为文本值可能会包含子元素,如您在示例中所述。
我建议你使用XSLT来转换文档,然后像现在这样使用XPath查询转换后的文档。另一种方法是编写你自己的解析器,它能够正确处理你的嵌套元素。
这XSLT可能会为你工作(还没有彻底测试):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="internalRef">
<xsl:value-of select="@xlink:href"/>
</xsl:template>
</xsl:stylesheet>
当然,你需要以改造原始文档使用XSLT处理器。
而且解析器看起来是这样的(注意,这是一个StAX的解析器只是骨架代码):
import java.io.StringReader;
import java.util.Iterator;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
public class ExampleStAXParser {
private static final int STATE_UNDEFINED = 1;
private static final int STATE_MAIN = 2;
private static final int STATE_STEP = 3;
private static final int STATE_PARA = 4;
private static final String EL_MAIN = "main";
private static final String EL_STEP = "step";
private static final String EL_PARA = "para";
private static final String EL_INTERNAL_REF = "internalRef";
private static final String ATT_HREF = "href";
private int state = STATE_UNDEFINED;
private String characters;
public void parse(String xmlString) throws XMLStreamException, Exception {
XMLEventReader reader = null;
try {
if (xmlString == null || xmlString.isEmpty()) {
throw new IllegalArgumentException("Illegal initializiation (xmlString is null or empty)");
}
StringReader stringReader = new StringReader(xmlString);
XMLInputFactory inputFact = XMLInputFactory.newInstance();
XMLStreamReader streamReader = inputFact.createXMLStreamReader(stringReader);
reader = inputFact.createXMLEventReader(streamReader);
while (reader.hasNext()) {
XMLEvent event = reader.nextEvent();
if (event.isCharacters()) {
characters(event);
}
if (event.isStartElement()) {
startElement(event);
// handle attributes
Iterator<Attribute> attributes = event.asStartElement().getAttributes();
while(attributes.hasNext()) {
attribute(attributes.next());
}
}
if (event.isEndElement()) {
endElement(event);
}
if (event.isStartDocument()) {
startDocument(event);
}
if (event.isEndDocument()) {
endDocument(event);
}
}
} catch (XMLStreamException ex) {
throw ex;
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (XMLStreamException ex) {
}
}
}
private void attribute(XMLEvent event) throws Exception {
if (state == STATE_PARA) {
Attribute attr = (Attribute) event;
String name = attr.getName().getLocalPart();
if (ATT_HREF.equals(name)) {
if (characters == null) {
characters = attr.getValue();
} else {
characters += attr.getValue();
}
}
} else
throw new Exception("unexpected attribute");
}
private void characters(XMLEvent event) throws Exception {
Characters asCharacters = event.asCharacters();
if (asCharacters.isWhiteSpace())
return;
if (state == STATE_PARA) {
if (characters == null) {
characters = asCharacters.getData();
} else {
characters += asCharacters.getData();
}
} else
throw new Exception("unexpected attribute");
}
private void startElement(XMLEvent event) throws Exception {
StartElement startElement = event.asStartElement();
String name = startElement.getName().getLocalPart();
switch (state) {
case STATE_UNDEFINED:
if (name.equals(EL_MAIN)) {
state = STATE_MAIN;
System.out.println("Element: " + name);
} else
throw new Exception("unexpected element");
break;
case STATE_MAIN:
if (name.equals(EL_STEP)) {
state = STATE_STEP;
System.out.println("Element: " + name);
} else
throw new Exception("unexpected element");
break;
case STATE_STEP:
if (name.equals(EL_PARA)) {
state = STATE_PARA;
System.out.println("Element: " + name);
} else
throw new Exception("unexpected element");
break;
case STATE_PARA:
if (name.equals(EL_INTERNAL_REF)) {
System.out.println("Element: " + name);
} else
throw new Exception("unexpected element");
break;
default:
throw new Exception("unexpected element");
}
}
private void endElement(XMLEvent event) throws Exception {
EndElement endElement = event.asEndElement();
String name = endElement.getName().getLocalPart();
switch (state) {
case STATE_MAIN:
if (name.equals(EL_MAIN)) {
state = STATE_UNDEFINED;
} else
throw new Exception("unexpected element");
break;
case STATE_STEP:
if (name.equals(EL_STEP)) {
state = STATE_MAIN;
} else
throw new Exception("unexpected element");
break;
case STATE_PARA:
if (name.equals(EL_INTERNAL_REF)) {
// do nothing
} else if (name.equals(EL_PARA)) {
System.out.println("Value: " + String.valueOf(characters));
characters = null;
state = STATE_STEP;
} else
throw new Exception("unexpected element");
break;
default:
throw new Exception("unexpected element");
}
}
private void startDocument(XMLEvent event) {
System.out.println("Parsing started");
}
private void endDocument(XMLEvent event) {
System.out.println("Parsing ended");
}
public static void main(String[] argv) throws XMLStreamException, Exception {
String xml = "";
xml += "<main>";
xml += "<step>";
xml += " <para>Calculate the values from the pool</para>";
xml += "</step>";
xml += "<step>";
xml += " <para>Use these(<internalRef id =\"003\" actuate=\"onRequest\" show=\"replace\" href=\"max003\"/>) values finally</para>";
xml += "</step>";
xml += "</main>";
ExampleStAXParser parser = new ExampleStAXParser();
parser.parse(xml);
}
}
或者这是无效XML的情况吗? – Napster
我想你可能会发现解析是看到内部标签作为''节点的子节点...即'' - >'' –
MadProgrammer
没有xml值中嵌套的xml标签这样的事情。 –