使用XSLT返回空的有效JSON对象

时间:2015-02-21 18:10:56

标签: xml json xslt

我们正在使用返回XML的Web服务,我们正在使用XSLT对日期进行排序,并仅将其中的一部分发送到移动客户端。返回到客户端的数据是JSON解析的。 在给定参数上,服务返回一个空XML - 如问题末尾所示。

在这种情况下我们想要做的是弄清楚如何将空的有效JSON对象(即[])返回给客户端。目前,我们无法更改Web服务本身的任何内容。任何想法都会有所帮助。

XML:

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://tempuri.org/">
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="">
      <xs:complexType>
        <xs:choice maxOccurs="unbounded">
          <xs:element name="Events">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Name" type="xs:string" minOccurs="0" />
                <xs:element name="boneId" type="xs:int" minOccurs="0" />
                <xs:element name="nsId" type="xs:int" minOccurs="0" />
                <xs:element name="objId" type="xs:int" minOccurs="0" />
                <xs:element name="fileName" type="xs:string" minOccurs="0" />
                <xs:element name="Date" type="xs:dateTime" minOccurs="0" />
                <xs:element name="ArieId" type="xs:int" minOccurs="0" />
                <xs:element name="EventPlaceName" type="xs:string" minOccurs="0" />
                <xs:element name="City" type="xs:int" minOccurs="0" />
                <xs:element name="PlaceFileName" type="xs:string" minOccurs="0" />
                <xs:element name="PlaceBoneId" type="xs:int" minOccurs="0" />
                <xs:element name="PlaceNsId" type="xs:int" minOccurs="0" />
                <xs:element name="PlaceObjId" type="xs:int" minOccurs="0" />
                <xs:element name="TourName" type="xs:string" minOccurs="0" />
                <xs:element name="TimeStart" type="xs:string" minOccurs="0" />
                <xs:element name="TimeEnd" type="xs:string" minOccurs="0" />
                <xs:element name="Genre" type="xs:int" minOccurs="0" />
                <xs:element name="Genre_Name" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" />
</DataSet>

XSLT:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:h="http://www.w3.org/1999/xhtml">
    <xsl:output method="text"/>
    <xsl:template match="Events">
        {
            'Items': [
                <xsl:for-each select="//Events">                                
                    {

                        'Name':             '<xsl:value-of select="Name"/>',
                        'Date':             '<xsl:value-of select="Date"/>',
                        'PlaceName':        '<xsl:value-of select="EventPlaceName"/>',
                        'boneId':           '<xsl:value-of select="boneId"/>',
                        'objId':            '<xsl:value-of select="objId"/>',
                        'PlaceNsId':        '<xsl:value-of select="PlaceNsId"/>',
                        'PlaceObjId':       '<xsl:value-of select="PlaceObjId"/>',
                        'StartPoint':       '<xsl:value-of select="StartPoint"/>',
                        'Description':      '<xsl:value-of select="Description"/>',
                        'Telephone':        '<xsl:value-of select="Telephone"/>'
                    },
                </xsl:for-each>
            ]       
        }
    </xsl:template>

</xsl:stylesheet>

来自服务的“常规”XML响应:

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://tempuri.org/">
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="">
      <xs:complexType>
        <xs:choice maxOccurs="unbounded">
          <xs:element name="Events">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Name" type="xs:string" minOccurs="0" />
                <xs:element name="boneId" type="xs:int" minOccurs="0" />
                <xs:element name="nsId" type="xs:int" minOccurs="0" />
                <xs:element name="objId" type="xs:int" minOccurs="0" />
                <xs:element name="fileName" type="xs:string" minOccurs="0" />
                <xs:element name="Date" type="xs:dateTime" minOccurs="0" />
                <xs:element name="ArieId" type="xs:int" minOccurs="0" />
                <xs:element name="EventPlaceName" type="xs:string" minOccurs="0" />
                <xs:element name="City" type="xs:int" minOccurs="0" />
                <xs:element name="PlaceFileName" type="xs:string" minOccurs="0" />
                <xs:element name="PlaceBoneId" type="xs:int" minOccurs="0" />
                <xs:element name="PlaceNsId" type="xs:int" minOccurs="0" />
                <xs:element name="PlaceObjId" type="xs:int" minOccurs="0" />
                <xs:element name="TourName" type="xs:string" minOccurs="0" />
                <xs:element name="TimeStart" type="xs:string" minOccurs="0" />
                <xs:element name="TimeEnd" type="xs:string" minOccurs="0" />
                <xs:element name="Genre" type="xs:int" minOccurs="0" />
                <xs:element name="Genre_Name" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <NewDataSet xmlns="">
      <Events diffgr:id="Events1" msdata:rowOrder="0">
        <Name>Name</Name>
        <boneId>1855</boneId>
        <nsId>305</nsId>
        <objId>28</objId>
        <fileName>tours_item_show.aspx</fileName>
        <ArieId>1</ArieId>
        <EventPlaceName>Place name</EventPlaceName>
        <City>392</City>
        <PlaceFileName>show_item_place.aspx</PlaceFileName>
        <PlaceBoneId>1563</PlaceBoneId>
        <PlaceNsId>201</PlaceNsId>
        <PlaceObjId>2574</PlaceObjId>
        <TourName>Tour name</TourName>
        <Genre>18</Genre>
        <Genre_Name>Group tours</Genre_Name>
      </Events>
    </NewDataSet>
  </diffgr:diffgram>
</DataSet>

3 个答案:

答案 0 :(得分:0)

我可能误解了这个问题,但这不仅仅是添加模板规则

的问题
<xsl:template match="diffgr:diffgram">[]</xsl:template>

答案 1 :(得分:0)

第一次将XML提供给包含多个Event节点的样式表时,您会发现不需要for-each。

但就主要问题而言 - 我们谈论的空虚有多么?我的意思是,零长度文件不是有效的XML。但是,如果你得到一个没有Event节点的NewDataSet,你应该在那个级别创建一个封闭对象,如果没有Events,你会自动获得一个空对象。有点像:

<xsl:template match="NewDataSet">
    {
    <xsl:apply-templates/>
    }
<xsl:template>

<强>更新

看到附加帖子(“常规”XML)后,我看到你正在处理的丑陋的Web服务。真?他们在每个响应中嵌入了模式,即使该响应没有给出数据?啊。

无论如何,我之前建议的变化应该有效。似乎你确信收到的一件事就是diffgram节点。因此,创建一个创建封闭JSON对象的那个。我建议你在你的XSL中添加一个xslns:diffgr声明 - local-name()就像欺骗我一样。

所以,你会按照以下方式做点什么:

<xsl:template match="diffgr:diffgram">
    {
    <xsl:apply-templates select="NewDataSet/Events"/>
    }
</xsl:template>

答案 2 :(得分:-1)

我对如何回答这个问题犹豫不决,因为即使响应包含数据,样式表也不会返回有效的JSON文档。因此,我建议您查看以下内容,并在必要时进行必要的调整。

以下样式表:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/*">
{<xsl:apply-templates select="*/NewDataSet"/>}
</xsl:template> 

<xsl:template match="NewDataSet">
"Items":[<xsl:apply-templates select="Events"/>]
</xsl:template> 

<xsl:template match="Events">
    {
        "Name":             "<xsl:value-of select="Name"/>",
        "Date":             "<xsl:value-of select="Date"/>",
        "PlaceName":        "<xsl:value-of select="EventPlaceName"/>",
        "boneId":           "<xsl:value-of select="boneId"/>",
        "objId":            "<xsl:value-of select="objId"/>",
        "PlaceNsId":        "<xsl:value-of select="PlaceNsId"/>",
        "PlaceObjId":       "<xsl:value-of select="PlaceObjId"/>",
        "StartPoint":       "<xsl:value-of select="StartPoint"/>",
        "Description":      "<xsl:value-of select="Description"/>",
        "Telephone":        "<xsl:value-of select="Telephone"/>"
    }
</xsl:template> 

</xsl:stylesheet>

应用于第二个输入XML示例时,将返回:

{
"Items":[
    {
        "Name":             "Name",
        "Date":             "",
        "PlaceName":        "Place name",
        "boneId":           "1855",
        "objId":            "28",
        "PlaceNsId":        "201",
        "PlaceObjId":       "2574",
        "StartPoint":       "",
        "Description":      "",
        "Telephone":        ""
    }
]
}

这与样式表产生的不完全相同 - 但它确实通过了验证:http://jsonlint.com/

相同样式表在应用于第一个输入XML示例时将返回:

{}

注意:我相信使用<xsl:text>输出文字文本可以更好地控制空格。