我尝试使用Xpath来读取XML。我没有从评估中获得任何结果的问题 公共类XPathUtils实现IXPath {
private Document doc;
private XPath xpath;
public XPathUtils(String baseString) throws HanaHttpConnectivityException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
try {
// resolve attacks on XML parsers - Fortify issue
docFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); //$NON-NLS-1$
docFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //$NON-NLS-1$
docFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$
docFactory.setFeature("http://xml.org/sax/features/namespaces", false); //$NON-NLS-1$
docFactory.setFeature("http://xml.org/sax/features/validation", false); //$NON-NLS-1$
docFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //$NON-NLS-1$
docFactory.setXIncludeAware(false);
docFactory.setValidating(false);
docFactory.setNamespaceAware(true);
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
InputStream inputs = new ByteArrayInputStream(baseString.getBytes());
doc = docBuilder.parse(inputs);
inputs.close();
xpath = XPathFactory.newInstance().newXPath();
} catch (ParserConfigurationException e) {
throw new HanaHttpConnectivityException(e);
} catch (SAXException e) {
throw new HanaHttpConnectivityException(e);
} catch (IOException e) {
throw new HanaHttpConnectivityException(e);
}
}
public Object getObjectValue(String strValue) throws HanaHttpConnectivityException {
try {
XPathExpression xpathExp = xpath.compile(strValue);
return xpathExp.evaluate(doc,XPathConstants.NODESET);
} catch (XPathExpressionException e) {
throw new HanaHttpConnectivityException(e);
}
}
public String getElementValue(String strValue) throws HanaHttpConnectivityException {
try {
XPathExpression xpathExp = xpath.compile(strValue);
return xpathExp.evaluate(doc);
} catch (XPathExpressionException e) {
throw new HanaHttpConnectivityException(e);
}
}
}
主要功能
try {
XPathUtils xpathUtil = new XPathUtils(metadata);
Object commandValue = xpathUtil.getObjectValue("/edmx:Edmx/edmx:DataServices/Schema");
NodeList nodes = (NodeList) commandValue;
for (int i = 0; i < nodes.getLength(); i++) {
String test2 = nodes.item(i).getNodeValue();
}
这是XML
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx
xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="3.0">
<Schema
xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration"
xmlns:sap="http://www.sap.com/Protocols/SAPData"
xmlns:rdl="http://www.sap.com/Protocols/SAPData/RDL"
xmlns="http://schemas.microsoft.com/ado/2009/11/edm"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" Namespace="app2">
<ComplexType Name="ApplicationView">
<Property Name="__ID" Type="Edm.Int64" Nullable="false"/>
</ComplexType>
<EntityType Name="test1_entityType">
<Key>
<PropertyRef Name="__ID"/>
</Key>
<Property Name="__ID" Type="Edm.Int64" Nullable="false"/>
</EntityType>
<EntityType Name="test2_entityType">
<Key>
<PropertyRef Name="__ID"/>
</Key>
<Property Name="__ID" Type="Edm.Int64" Nullable="false"/>
</EntityType>
<EntityContainer Name="__container" m:IsDefaultEntityContainer="true">
<EntitySet Name="test1" EntityType="app2.test1_entityType"/>
<EntitySet Name="test2" EntityType="app2.test2_entityType"/>
<FunctionImport Name="action1" IsSideEffecting="true" IsBindable="true" rdl:source-object="action">
<Parameter Name="bindingParam" Type="app2.test1_entityType"/>
</FunctionImport>
<FunctionImport Name="action2" IsSideEffecting="true" IsBindable="true" rdl:source-object="action">
<Parameter Name="bindingParam" Type="app2.test1_entityType"/>
</FunctionImport>
<FunctionImport Name="action3" IsSideEffecting="true" IsBindable="true" rdl:source-object="action">
<Parameter Name="bindingParam" Type="app2.test2_entityType"/>
</FunctionImport>
<FunctionImport Name="action4" IsSideEffecting="true" IsBindable="true" rdl:source-object="action">
<Parameter Name="bindingParam" Type="app2.test2_entityType"/>
</FunctionImport>
<FunctionImport Name="globalAction" IsSideEffecting="true" IsBindable="false" rdl:source-object="action"/>
<FunctionImport Name="ApplicationView" IsSideEffecting="false" IsBindable="false" rdl:source-object="view">
<ReturnType Type="Collection(ApplicationView)"/>
</FunctionImport>
</EntityContainer>
</Schema>
<Schema
xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration"
xmlns:sap="http://www.sap.com/Protocols/SAPData"
xmlns:rdl="http://www.sap.com/Protocols/SAPData/RDL"
xmlns="http://schemas.microsoft.com/ado/2009/11/edm"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" Namespace="app2.metadataParent">
<ComplexType Name="MyView">
<Property Name="myElement" Type="Edm.String" MaxLength="5000" Unicode="true"/>
</ComplexType>
<EntityType Name="MyEntity_entityType">
<Key>
<PropertyRef Name="__ID"/>
</Key>
<Property Name="__ID" Type="Edm.Int64" Nullable="false"/>
<Property Name="myElement" Type="Edm.String" MaxLength="5000" Unicode="true"/>
</EntityType>
<EntityContainer Name="__container" m:IsDefaultEntityContainer="false">
<EntitySet Name="MyEntity" EntityType="app2.metadataParent.MyEntity_entityType"/>
<FunctionImport Name="myAction" IsSideEffecting="true" IsBindable="true" rdl:source-object="action">
<ReturnType Type="Edm.String" MaxLength="5000" Unicode="true"/>
<Parameter Name="bindingParam" Type="app2.metadataParent.MyEntity_entityType"/>
</FunctionImport>
<FunctionImport Name="MyView" IsSideEffecting="false" IsBindable="false" rdl:source-object="view">
<ReturnType Type="Collection(MyView)"/>
</FunctionImport>
</EntityContainer>
</Schema>
<Schema
xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration"
xmlns:sap="http://www.sap.com/Protocols/SAPData"
xmlns:rdl="http://www.sap.com/Protocols/SAPData/RDL"
xmlns="http://schemas.microsoft.com/ado/2009/11/edm"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" Namespace="app2.metadataParent.metadata2Child">
<EntityType Name="xxx_entityType">
<Key>
<PropertyRef Name="__ID"/>
</Key>
<Property Name="__ID" Type="Edm.Int64" Nullable="false"/>
</EntityType>
<EntityContainer Name="__container" m:IsDefaultEntityContainer="false">
<EntitySet Name="xxx" EntityType="app2.metadataParent.metadata2Child.xxx_entityType"/>
<FunctionImport Name="xxxyyy" IsSideEffecting="true" IsBindable="true" rdl:source-object="action">
<Parameter Name="bindingParam" Type="app2.metadataParent.metadata2Child.xxx_entityType"/>
</FunctionImport>
</EntityContainer>
</Schema>
<Schema
xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration"
xmlns:sap="http://www.sap.com/Protocols/SAPData"
xmlns:rdl="http://www.sap.com/Protocols/SAPData/RDL"
xmlns="http://schemas.microsoft.com/ado/2009/11/edm"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" Namespace="app2.metadataNotChild">
<EntityType Name="ffgg_entityType">
<Key>
<PropertyRef Name="__ID"/>
</Key>
<Property Name="__ID" Type="Edm.Int64" Nullable="false"/>
</EntityType>
<EntityContainer Name="__container" m:IsDefaultEntityContainer="false">
<EntitySet Name="ffgg" EntityType="app2.metadataNotChild.ffgg_entityType"/>
<FunctionImport Name="gghh" IsSideEffecting="true" IsBindable="true" rdl:source-object="action">
<Parameter Name="bindingParam" Type="app2.metadataNotChild.ffgg_entityType"/>
</FunctionImport>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
我也尝试使用
"//edmx:Edmx//edmx:DataServices//Schema/Namespace"
"//edmx:Edmx//edmx:DataServices//Schema//Namespace"
你知道为什么我没有成功获得任何结果吗?
答案 0 :(得分:1)
您的Schema
元素
xmlns="http://schemas.microsoft.com/ado/2009/11/edm"
这意味着它(及其所有未加前缀的子节点)都在此命名空间中,因此在XPath表达式中不会被.../Schema
匹配(XPath表达式中的未加前缀的名称始终引用没有名称空间。)
您需要向XPath
实例提供NamespaceContext
,告诉他们如何解析命名空间URI的前缀。遗憾的是,标准Java类库中没有此接口的默认实现,但是存在第三方实现,例如SimpleNamespaceContext from the Spring Framework,或者创建自己的相当简单。以Spring实现为例,它是这样的:
public class XPathUtils implements IXPath {
private Document doc;
private XPath xpath;
private SimpleNamespaceContext nsCtx;
public XPathUtils(String baseString) throws HanaHttpConnectivityException {
// as before
// .......
xpath = XPathFactory.newInstance().newXPath();
nsCtx = new SimpleNamespaceContext();
xpath.setNamespaceContext(nsCtx);
}
public Object getObjectValue(String strValue, String... namespaces) throws HanaHttpConnectivityException {
try {
if(namespaces != null) {
// namespaces array is [prefix1, uri1, prefix2, uri2, ...]
for(int i = 0; i < namespaces.length; i++) {
nsCtx.bindNamespaceUri(namespaces[i], namespaces[++i]);
}
}
XPathExpression xpathExp = xpath.compile(strValue);
return xpathExp.evaluate(doc,XPathConstants.NODESET);
} catch (XPathExpressionException e) {
throw new HanaHttpConnectivityException(e);
} finally {
nsCtx.clear();
}
}
}
除了为edmx
提供http://schemas.microsoft.com/ado/2007/06/edmx
前缀的绑定之外,您还需要将前缀(例如edm
)绑定到http://schemas.microsoft.com/ado/2009/11/edm
命名空间并使用你的XPath中的前缀:
NodeList namespaceAttributes = (NodeList)xpathUtil.getObjectValue(
"/edmx:Edmx/edmx:DataServices/edm:Schema/@Namespace",
"edmx", "http://schemas.microsoft.com/ado/2007/06/edmx",
"edm", "http://schemas.microsoft.com/ado/2009/11/edm");