0

尝试执行转换以从 XML 文档中获取 JSON 文件已经有好几天了。我的 xml 文档有不同级别的子节点,我在互联网上找到的所有示例都没有抓住我的情况。这是我的 xml 示例:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <foo id="1" group="B" />
    <foo id="2" group="A" />
    <foo id="3", group="A">
        <foo id="4" group="A" />
        <foo id="5" group="A">
            <foo id="6" group="A" />
            <foo id="7" group="A" />
            <foo id="8" group="A" />
        </foo>
    </foo>
    <foo id="9" group="A"></foo>
</root>

所需的 JSON:

{
    "B": {
        "id": 1
    },
    "A": {
        "id": 2
    },
    "A": [{
            "id": 4
        },
        {
            "A": [{
                    "id": 6
                },
                {
                    "id": 7
                },
                {
                    "id": 8
                }
            ]
        }
    ],
    "A": {
        "id": 9
    }
}

意味着每当我有嵌套<foo>元素时,子元素都会与父元素组合在一起,依此类推。

我尝试了一些 xsl 代码(see1see2),但未能使它们适用于我的情况。

4

3 回答 3

0

不太清楚您想要哪个结果,因为如果有各种foo group="A"元素,所需的“JSON”具有重复的属性,但通常 XML 到 JSON 生成,您可以使用支持 XPath 3.1 映射和数组的 XSLT 3 ( https://www .w3.org/TR/xpath-31/#id-maps-and-arrays)和json输出方法或xml-to-json函数(https://www.w3.org/TR/xslt-30/#json , https:// /www.w3.org/TR/xslt-30/#func-xml-to-json),这样你有两种方法来创建 JSON 并输出它,你可以将你的 XML 直接转换为 XPath 3.1 映射/数组和序列化它们,<xsl:output method="json"/>或者您可以使用通常的 XSLT 处理将您的输入 XML 转换为 JSON XML 表示xml-to-json函数期望并应用它来获取 JSON 作为文本。

这是第一种方法的示例:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-skip"/>
  <xsl:strip-space elements="*"/>

  <xsl:output method="json" indent="yes"/>

  <xsl:template match="*[*]">
      <xsl:map>
          <xsl:for-each-group select="foo" group-by="@group">
              <xsl:map-entry key="string(current-grouping-key())">
                  <xsl:choose>
                      <xsl:when test="not(tail(current-group()))">
                          <xsl:apply-templates select="current-group()"/>
                      </xsl:when>
                      <xsl:otherwise>
                          <xsl:variable name="group-transform" as="map(*)*">
                              <xsl:apply-templates select="current-group()"/>
                          </xsl:variable>
                          <xsl:sequence select="array { $group-transform }"/>
                      </xsl:otherwise>
                  </xsl:choose>
              </xsl:map-entry>
          </xsl:for-each-group>
      </xsl:map>
  </xsl:template>


  <xsl:template match="*[not(*)]">
      <xsl:sequence select="map { 'id' : data(@id) }"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/6r5Gh3i

这是第二个之一:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="#all"
    xmlns="http://www.w3.org/2005/xpath-functions"
    expand-text="yes"
    version="3.0">

  <xsl:mode on-no-match="shallow-skip"/>
  <xsl:strip-space elements="*"/>

  <xsl:output method="text"/>

  <xsl:variable name="json-xml">
      <xsl:apply-templates/>
  </xsl:variable>

  <xsl:template match="/">
      <xsl:sequence select="xml-to-json($json-xml, map { 'indent' : true() })"/>
  </xsl:template>

  <xsl:template match="*[*]">
      <map>
          <xsl:for-each-group select="foo" group-by="string(@group)">
              <xsl:choose>
                  <xsl:when test="not(tail(current-group()))">
                      <map key="{current-grouping-key()}">
                          <string key="id">{@id}</string>
                      </map>
                  </xsl:when>
                  <xsl:otherwise>
                      <array key="{current-grouping-key()}">
                          <xsl:apply-templates select="current-group()"/>
                      </array>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:for-each-group>          
      </map>
  </xsl:template>

  <xsl:template match="*[not(*)]">
      <map>
          <string key="id">{@id}</string>
      </map>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/6r5Gh3i/5

XSLT 3 可在 Sourceforge 和 Maven https://mvnrepository.com/artifact/net.sf.saxon/Saxon-HE/9.9.1-2上的 Java 平台上使用 Saxon 9.8 或 9.9 HE 以及.NET 平台上NuGet https://www.nuget.org/packages/Saxon-HE/

于 2019-04-09T10:27:54.703 回答
0
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:strip-space elements="*"/>
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="root">
        <xsl:text>{</xsl:text>
        <xsl:apply-templates select="//foo"/>
        <xsl:text>}</xsl:text>
    </xsl:template>
    <xsl:template match="//foo">
        <xsl:choose>
            <xsl:when test=" count(ancestor::foo) = 1 and child::foo"/>
            <xsl:when test="foo[child::foo]"/>
            <xsl:otherwise>
                <xsl:text>&quot;</xsl:text><xsl:value-of select="@group"/><xsl:text>&quot;</xsl:text>:<xsl:text> {&#x0A;</xsl:text>
                <xsl:text>      &quot;</xsl:text><xsl:value-of select="@id/name()"/><xsl:text>&quot;</xsl:text>:<xsl:value-of select=" concat(' ',@id)"/>
                <xsl:text>&#x0A; },</xsl:text>
            </xsl:otherwise>
        </xsl:choose>     
    </xsl:template>    
</xsl:stylesheet>
于 2019-04-09T05:56:47.553 回答
0

请检查此代码:

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <xsl:template match="root">
        <xsl:text>{</xsl:text>
        <xsl:text>&#x0A;</xsl:text>
        <xsl:for-each select="foo">
            <xsl:if test="not(child::foo)">
                    <xsl:text>    "</xsl:text><xsl:value-of select="@group"/><xsl:text>": </xsl:text><xsl:text>{</xsl:text><xsl:text>&#x0A;</xsl:text>
                    <xsl:text>        "id": </xsl:text><xsl:value-of select="@id"/><xsl:text>&#x0A;</xsl:text>
                    <xsl:text>    }</xsl:text>
                <xsl:if test="position()!=last()">
                    <xsl:text>,</xsl:text>
                </xsl:if>
                <xsl:text>&#x0A;</xsl:text>
            </xsl:if>
                    <xsl:for-each select="foo">
                        <xsl:if test="not(child::foo)">
                            <xsl:text>    "</xsl:text><xsl:value-of select="@group"/><xsl:text>": </xsl:text><xsl:if test="parent::foo"><xsl:text>[</xsl:text></xsl:if><xsl:text>{</xsl:text><xsl:text>&#x0A;</xsl:text>
                        <xsl:text>            "id": </xsl:text><xsl:value-of select="@id"/><xsl:text>&#x0A;</xsl:text>
                            <xsl:text>        },</xsl:text><xsl:text>&#x0A;</xsl:text>
                            <xsl:text>        {</xsl:text><xsl:text>&#x0A;</xsl:text>
                            <xsl:text>        "</xsl:text><xsl:value-of select="@group"/><xsl:text>": </xsl:text><xsl:text>[</xsl:text><xsl:text>&#x0A;</xsl:text>
                        </xsl:if>

                           <!-- <xsl:text>        "</xsl:text><xsl:value-of select="@group"/><xsl:text>": </xsl:text><xsl:text>[{</xsl:text><xsl:text>&#x0A;</xsl:text>-->
                        <xsl:for-each select="foo">
                            <xsl:text>              {</xsl:text><xsl:text>&#x0A;</xsl:text>
                            <xsl:text>                 "id": </xsl:text><xsl:value-of select="@id"/><xsl:text>&#x0A;</xsl:text>
                            <xsl:text>              }</xsl:text>
                            <xsl:if test="position()!=last()">
                                <xsl:text>,</xsl:text>
                            </xsl:if><xsl:text>&#x0A;</xsl:text>
                            <xsl:if test="position()=last()">
                                <xsl:text>       ]</xsl:text><xsl:text>&#x0A;</xsl:text>
                            </xsl:if>
                            <xsl:if test="position()=last()">
                                <xsl:text>   }</xsl:text><xsl:text>&#x0A;</xsl:text>
                            </xsl:if>
                            <xsl:if test="position()=last()">
                                <xsl:text>],</xsl:text><xsl:text>&#x0A;</xsl:text>
                            </xsl:if>
                            <xsl:text>&#x0A;</xsl:text>
                        </xsl:for-each>
                    </xsl:for-each>
        </xsl:for-each>
        <xsl:text>}</xsl:text>
    </xsl:template>

</xsl:stylesheet>
于 2019-04-09T08:59:34.403 回答