首页 > 解决方案 > 使用 Java 将此 xml 文件解析为指定 JSON 的最简单方法是什么?

问题描述

正文和摘要由一系列段落组成,每个段落都可以有内嵌引用。我最担心的是段落中包含的信息。我现在可以将引文留空。还有一件事,每个段落可以属于一个主要部分和多个小节。

我被要求将小节层次结构实现为“subsection1.subsection2.subsection3”,它通过用点分隔小节来说明层次结构。一开始是想用XOM把xml解析成POJO,然后用GSON把它序列化成JSON。有没有更简单的方法可以采取?

XML(有点长)

全文文档的 JSON 模式

{
    "paper_id": <str>,                      # 40-character sha1 of the PDF
    "metadata": {
        "title": <str>,
        "authors": [                        # list of author dicts, in order
            {
                "first": <str>,
                "middle": <list of str>,
                "last": <str>,
                "suffix": <str>,
                "affiliation": <dict>,
                "email": <str>
            },
            ...
        ],
        "abstract": [                       # list of paragraphs in the abstract
            {
                "text": <str>,
                "cite_spans": [             # list of character indices of inline citations
                                            # e.g. citation "[7]" occurs at positions 151-154 in "text"
                                            #      linked to bibliography entry BIBREF3
                    {
                        "start": 151,
                        "end": 154,
                        "text": "[7]",
                        "ref_id": "BIBREF3"
                    },
                    ...
                ],
                "ref_spans": <list of dicts similar to cite_spans>,     # e.g. inline reference to "Table 1"
                "section": "Abstract"
            },
            ...
        ],
        "body_text": [                      # list of paragraphs in full body
                                            # paragraph dicts look the same as above
            {
                "text": <str>,
                "cite_spans": [],
                "ref_spans": [],
                "eq_spans": [],
                "section": "Introduction"
            },
            ...
            {
                ...,
                "section": "Conclusion"
            }
        ],
        "bib_entries": {
            "BIBREF0": {
                "ref_id": <str>,
                "title": <str>,
                "authors": <list of dict>       # same structure as earlier,
                                                # but without `affiliation` or `email`
                "year": <int>,
                "venue": <str>,
                "volume": <str>,
                "issn": <str>,
                "pages": <str>,
                "other_ids": {
                    "DOI": [
                        <str>
                    ]
                }
            },
            "BIBREF1": {},
            ...
            "BIBREF25": {}
        },
        "ref_entries":
            "FIGREF0": {
                "text": <str>,                  # figure caption text
                "type": "figure"
            },
            ...
            "TABREF13": {
                "text": <str>,                  # table caption text
                "type": "table"
            }
        },
        "back_matter": <list of dict>           # same structure as body_text
    }
}

标签: xmlparsing

解决方案


“最简单”在很大程度上取决于您的技能。

我会使用 XSLT 3.0 来完成。在 XSLT 3.0 中有几种方法可以处理任务;我想我会用构造映射和数组的模板规则来做,然后使用 JSON 序列化方法将映射和数组的结果结构转换为 JSON。以下是您可能使用的两个模板规则,作为示例:

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

<xsl:template match="tei:biblStruct/tei:analytic">
  <xsl:map:entry key="'authors'" select="f:array-from(tei:author)"/>
</xsl:template>

<xsl:template match="tei:author">
  <xsl:map>
    <xsl:if test="tei:persName/tei:firstName">
       <xsl:map:entry key="'first'" select="string(tei:persName/tei:firstName)"/>
    </xsl:if>
    <xsl:if test="tei:persName/tei:lastName">
       <xsl:map:entry key="'last'" select="string(tei:persName/tei:lastName)"/>
    </xsl:if>
    ...
</xsl:template>

不幸的是,缺少xsl:array构造数组的指令。如果您使用 Saxon-PE 或更高版本,您可以使用saxon:array扩展指令来填补这一空白,但您也可以通过编写自己的函数来解决限制,如下所示(您只需执行一次):

<xsl:function name="f:array-from" as="array(*)">
  <xsl:param name="elements" select="element(*)*"/>
  <xsl:variable name="out" as="item()*">
    <xsl:apply-templates select="$elements"/>
  </xsl:variable>
  <xsl:sequence select="array{$out}"/>
</xsl:function>

推荐阅读