Java Web 服务返回带有 > 的字符串 和 < 而不是 > 和 <
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7849666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Web Service returns string with > and < instead of > and <
提问by Sababado
I have a java web service that returns a string. I'm creating the body of this xml string with a DocumentBuilder
and Document
class. When I view source of the returned XML (Which looks fine in the browser window) instead of <> it's returning <
and >
around the XML nodes.
我有一个返回字符串的 Java Web 服务。我正在用 aDocumentBuilder
和Document
类创建这个 xml 字符串的主体。当我查看返回的 XML 的源代码(在浏览器窗口中看起来不错)而不是 <> 时,它正在返回<
并>
围绕 XML 节点。
Please help.
请帮忙。
****UPDATE (including code example)
The code is not including any error catching, it was stripped for simplicity.
One code block and three methods are included:
The first code block (EXAMPLE SETUP) shows the basics of what the Document object is setup to be like. the method appendPayment(...)
is where the actual document building happens. It calls on two helper methods getTagValue(...)
and prepareElement(...)
**Note, this code is meant to copy specific parts from a pre-existing xml string, xmlString
, and grap the necessary information to be returned later.
****UPDATE (包括代码示例)
代码不包括任何错误捕获,为了简单起见,它被剥离了。包括一个代码块和三个方法: 第一个代码块(EXAMPLE SETUP)显示了 Document 对象设置的基础知识。该方法appendPayment(...)
是实际文档构建发生的地方。它调用两个辅助方法getTagValue(...)
和prepareElement(...)
**注意,此代码旨在从预先存在的 xml 字符串中复制特定部分xmlString
,并获取稍后返回的必要信息。
****UPDATE 2Response added at the end of the question
****更新 2在问题末尾添加了回复
************ Follow-up question to the first answer is here:
How to return arbitrary XML Document using an Eclipse/AXIS2 POJO Service
************ 第一个答案的后续问题在这里:
如何使用 Eclipse/AXIS2 POJO 服务返回任意 XML 文档
EXAMPLE SETUP
{
//create new document
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder newDocBuilder = docFactory.newDocumentBuilder();
Document newDoc = newDocBuilder.newDocument();
Element rootElement = newDoc.createElement("AllTransactions");
newDoc.appendChild(rootElement);
appendPayment(stringXML, newDoc);
}
public static void appendPayment(String xmlString, Document newDoc) throws Exception
{
//convert string to inputstream
ByteArrayInputStream bais = new ByteArrayInputStream(xmlString.getBytes());
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document oldDoc = docBuilder.parse(bais);
oldDoc.getDocumentElement().normalize();
NodeList nList = oldDoc.getChildNodes();
Node nNode = nList.item(0);
Element eElement = (Element) nNode;
//Create new child node for this payment
Element transaction = newDoc.createElement("Transaction");
newDoc.getDocumentElement().appendChild(transaction);
//status
transaction.appendChild(prepareElement("status", eElement, newDoc));
//amount
transaction.appendChild(prepareElement("amount", eElement, newDoc));
}
private static String getTagValue(String sTag, Element eElement)
{
NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
return nValue.getNodeValue();
}
private static Element prepareElement(String sTag, Element eElement, Document newDoc)
{
String str = getTagValue(sTag, eElement);
Element newElement = newDoc.createElement(sTag);
newElement.appendChild(newDoc.createTextNode(str));
return newElement;
}
Finally, I use the following method to convert the final Document
object to a String
最后,我使用以下方法将最终Document
对象转换为String
public static String getStringFromDocument(Document doc)
{
try
{
DOMSource domSource = new DOMSource(doc);
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(domSource, result);
return writer.toString();
}
catch(TransformerException ex)
{
ex.printStackTrace();
return null;
}
}
The header type of the response is as follows
响应头类型如下
Server: Apache-Coyote/1.1
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
This is an example response
这是一个示例响应
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<getTransactionsResponse xmlns="http://services.paypal.com">
<getTransactionsReturn><AllTransactions><Transaction><status>PENDING</status><amount>55.55</amount></transaction>
</getTransactionsResponse>
</soapenv:Body>
</soapenv:Envelope>
回答by maerics
The framework is doing what you tell it; your method returns a String
which means the generated WSDL should have a response message of type <xsd:string>
. As we know, XML strings must encode certain characters as character entity references(i.e. "<
" becomes "<
" so the XML parser treats it as a string, not the beginning of an XML element as you intend). If you want to return an XML document then you must define the XML structure in the WSDL <types>
sectionand set the response message part to the appropriate element.
框架正在做你告诉它的事情;您的方法返回 a String
,这意味着生成的 WSDL 应具有类型为 的响应消息<xsd:string>
。正如我们所知,XML 字符串必须将某些字符编码为字符实体引用(即“ <
” 变为“ <
”,因此 XML 解析器将其视为字符串,而不是您想要的 XML 元素的开头)。如果要返回 XML 文档,则必须在WSDL<types>
部分定义 XML 结构并将响应消息部分设置为适当的元素。
To put it another way, you are trying to send "typed" data without using the strong type system provided by SOAP/WSDL (namely XML schema); this is generally regarded as bad design (see Loosely typed versus strongly typed web services).
换句话说,您试图在不使用 SOAP/WSDL 提供的强类型系统(即 XML 模式)的情况下发送“类型化”数据;这通常被认为是糟糕的设计(请参阅松散类型与强类型 Web 服务)。
The ultimate solution is to to define the response document via a proper XML Schema. If there is no set schema, as by the design of your service, then use the <xsd:any>
type for the message response type, although this approach has its pitfalls. Moreover, such a redesign implies a schema-first (top-down) development model and from the comment stream it seems that you are currently practicing code-first (bottom-up) approach. Perhaps your tools provide a mechanism such as a "general XML document" return type or annotation which achieves the same effect.
最终的解决方案是通过适当的XML Schema定义响应文档。如果根据您的服务设计没有设置模式,则使用<xsd:any>
消息响应类型的类型,尽管这种方法有其缺陷。此外,这种重新设计意味着模式优先(自上而下)开发模型,从评论流看来,您目前正在实践代码优先(自下而上)方法。也许您的工具提供了一种机制,例如“通用 XML 文档”返回类型或实现相同效果的注释。