如何查询由 json-to-xml 生成的 XML 文档节点

How to query a XML document-node produced by json-to-xml

我希望导入 JSON 数据以使用 XSLT 进行处理并获得结果 XML。我确实理解“json-to-xml”所做的解析意味着由其他映射、数组、键和值组成的映射的结果。我不遵循的是应该使用什么语法来查询地图。似乎第一步总是从 JSON 文件解析根级别的完整标记内容。我假设在解析“json-to-xml”之后的任何进一步查询都是针对文档生成节点进行的。

在下面的示例中,我从一个具有层次结构的 JSON 文件开始,但最终结果应该几乎是完全平坦的。 “一般”和“单位定义”(在 JSON 文件中)应用作有关如何转换数据的指导,例如使用哪个属性,但 JSON 中的键级别不应出现在 XML 结果中。

我已经阅读了关于“json-to-xml”的 XSL 3.0 规范,但我没有找到任何针对生成的文档节点的查询示例。 https://www.w3.org/TR/xslt-30/#func-json-to-xml

下面的代码也可以在这里找到:https://xsltfiddle.liberty-development.net/jxWZS6Y/1

澄清问题: 如何查询 json-to-xml 生成的地图,以获得低于“想要的结果”?

我的尝试:

XML数据源文件:

<data>
{
    "general": {
      "Language": "English",
      "Country": "Sweden"
    },

    "units-definitions": {
      "SEK": "iso4217:SEK"
    }
  }
</data>

XSL:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"
    xmlns:root="http://www.example.org/1"
    xmlns:flat="http://www.example.org/2"
>

  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:template match="data">
      <!-- New root tag name -->
      <root:report>
          <xsl:apply-templates select="json-to-xml(.)"/>
      </root:report>
  </xsl:template>
  
  <xsl:template
  match="*[@key]"
  xpath-default-namespace="http://www.w3.org/2005/xpath-functions"
>
    <xsl:element name="flat:{@key}">
      <xsl:attribute name="contextRef">period0</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:element>

</xsl:template>
  
</xsl:stylesheet>

结果:

<!DOCTYPE HTML>
<root:report xmlns:root="http://www.example.org/1" xmlns:flat="http://www.example.org/2">
   <flat:general contextRef="period0">
      <flat:Language contextRef="period0">English</flat:Language>
      <flat:Country contextRef="period0">Sweden</flat:Country>
   </flat:general>
   <flat:units-definitions contextRef="period0">
      <flat:SEK contextRef="period0">iso4217:SEK</flat:SEK>
   </flat:units-definitions>
</root:report>

想要的结果:

<?xml version="1.0" encoding="UTF-8"?>

<root:report
  xmlns:root="http://www.example.org/1"
  xmlns:flat="http://www.example.org/2"
  >
      <flat:Language contextRef="period0">English</base:Language>
      <flat:Country contextRef="period0">Sweden</base:Country>
      <flat:SEK contextRef="balance0">iso4217:SEK</base:SEK>
</root:report>

如果你想展平一些你通常处理的结构 //* 或者在那种情况下只处理叶元素 //*[@key and not(*)]:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:root="http://www.example.org/1"
  xmlns:flat="http://www.example.org/2"
  exclude-result-prefixes="xs"
  expand-text="yes">

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

  <xsl:template match="data">
    <root:report>
      <xsl:apply-templates select="json-to-xml(.)//*[@key and not(*)]"/>
    </root:report>
  </xsl:template>
  
  <xsl:template match="*[@key]">
    <xsl:element name="flat:{@key}">
      <xsl:attribute name="contextRef">period0</xsl:attribute>
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

为了产生你想要的结果,我不认为我会使用 json-to-xml(),我会直接处理 JSON。类似于:

<xsl:template match="data">
    <root:report>
      <xsl:variable name="json" select="parse-json(.)"/>
      <flat:Language contextRef="period0">{?general?Language}</flat:Language>
      <flat:Country contextRef="period0">{?general?Country}</flat:Country>
      <flat:SEK contextRef="period0">{?units-definitions?SEK}</flat:SEK>
    </root:report>
</xsl:template>

我从你对@MartinHonnen 的回答的评论中看到你简化了实际问题,但我认为这种方法应该证明具有足够的可扩展性。