【问题标题】:xslt to convert to jsonxslt 转换为 json
【发布时间】:2015-02-20 18:14:13
【问题描述】:

我得到的输入:

  <table>   
    <source1>
      <ptr>
          <data name="text1">20431</data>
          <data name="text2">collins</data>
          <data name="text3">20141231></data>
          <data name="text4">regard</data>
      </ptr>
    </source1>
    <source2>
        <ptr>
            <data name="note1">C</data>
            <data name="note2">A</data>
            <data name="note3">22356</data>
            <data name="note4">465506</data>
            <data name="note5">434562491057912</data>
            <data name="note6">milk</data>
            <data name="note7">dfRTA</data>
        </ptr>
    </source2>
    <source3>
    <enroll>n</enroll>
    </source3>
    </table>

需要把这个转成json为

{
"table":
{
"source1":
{"text1":"20431",
"text2": "collins",
"text3": "20141231",
"text4" :"regard"
},
"source2":
{"note1":"20431",
"note2": "A",
"note3":"22356",
"note4":"465506",
"note5":"434562491057912",
"note6":"milk",
"note7":"dfRTA"
}
}}

如何使用 xsl 转换任何通用的而不是匹配每个属性名称。 任何人都有可以进行上述转换的样式表

【问题讨论】:

  • 什么决定了 JSON 中使用了哪些元素(例如tablesource1)和不使用哪些元素(例如ptrenroll)?
  • 那些是固定的,所有带有“数据”的元素都需要转换为json。那是reqmnet
  • tablesource1source2 出现在输出中但不是“数据”(并且table 也是数据元素的父元素)。因此,问题是:一个例子不做一个规范。
  • 我支持使用 XSLT 避免方形钉通过圆孔的建议。由于内容阻抗 (JSON!= XML) 和相关缺乏进行正确转换所需的元数据,这是有问题的。如果您碰巧有表达内容的实际 proglang 对象,将 XML 读入其中,然后以 JSON 格式编写会导致更好的数据转换。

标签: xml json xslt xslt-1.0


【解决方案1】:

正如评论中已经提到的,XSLT is generally the wrong tool to produce JSON。但是,如果您已经检查了提供的链接,并且仍然想测试它是否符合您的要求或其他原因,那么 XSLT 会生成一个文本文件,对于您的示例输入 XML,该文件是有效的 JSON 格式:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" doctype-public="XSLT-compat" 
     omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
  <xsl:template match="table">
    <xsl:text>{ "table" : {</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>}}</xsl:text>
  </xsl:template>
  <xsl:template match="*[starts-with(local-name(),'source') and .//data]">
    <xsl:text>"</xsl:text>
    <xsl:value-of select="local-name()"/>
    <xsl:text>" :</xsl:text>
    <xsl:text>{</xsl:text>
    <xsl:apply-templates select="@*|node()"/>
    <xsl:text>}</xsl:text>
    <xsl:if test="following-sibling::*[starts-with(local-name(),'source') 
                                            and .//data]">
        <xsl:text>, </xsl:text>
    </xsl:if>
  </xsl:template>
  <xsl:template match="data">
    <xsl:text>"</xsl:text>
    <xsl:value-of select="@name"/>
    <xsl:text>" : "</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>"</xsl:text>
    <xsl:if test="following-sibling::data">
        <xsl:text>, </xsl:text>
    </xsl:if>
  </xsl:template>
  <xsl:template match="*[starts-with(local-name(),'source') 
                              and not(.//data)]"/>
</xsl:transform>

当应用于您的输入 XML 时,会产生以下输出:

{ "table" : {   
"source1" :{

      "text1" : "20431", 
      "text2" : "collins", 
      "text3" : "20141231>", 
      "text4" : "regard"
}, 
"source2" :{

        "note1" : "C", 
        "note2" : "A", 
        "note3" : "22356", 
        "note4" : "465506", 
        "note5" : "434562491057912", 
        "note6" : "milk", 
        "note7" : "dfRTA"
}
}}

虽然从输入中不完全清楚,但您在评论中提到所有数据元素都需要转换,因此我排除了名称以 source 开头且没有名称为 data 的子节点的每个父元素(@ 987654326@ 在您的示例中)并在最后应用一个空模板以将其从输出中删除。
请注意,为了提高性能,可以改进检查 source 节点是否包含任何 data 节点的表达式,具体取决于输入 - 例如如果已知包含data 的源始终包含在ptr 中,最好将&lt;xsl:template match="*[starts-with(local-name(),'source') and .//data]"&gt; 之类的匹配模式调整为&lt;xsl:template match="*[starts-with(local-name(),'source') and ptr]"&gt;(或ptr/data,以防可能出现空的ptr 元素)。
如果您想从输出中删除不必要的空间,您可以在&lt;xsl:output&gt; 下方添加&lt;xsl:strip-space elements="*"/&gt; 以将生成的文本/“JSON”放在一行中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-24
    • 2020-01-26
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    相关资源
    最近更新 更多