[英]xpath doesn't return any value
我试图使用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"
您知道为什么我没有成功吗?
您的Schema
元素具有
xmlns="http://schemas.microsoft.com/ado/2009/11/edm"
这意味着它(及其所有未加前缀的子代)都在此命名空间中,因此不会与XPath表达式中的.../Schema
匹配(XPath表达式中的未前缀名称始终引用任何命名空间中的元素)。
您需要为XPath
实例提供NamespaceContext
,告诉它们如何解析名称空间URI的前缀。 不幸的是,标准Java类库中没有该接口的默认实现,但是有第三方实现,例如Spring Framework中的SimpleNamespaceContext ,或者创建自己的接口也很简单。 以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");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.