如何将多级 xml 扁平化为 java 中的列表 <String xpath >?

How to flatten a multilevel xml into List<String xpath > in java?

objective 是将多级重复 xml 扁平化为叶级别的 xpath;这样我们就可以将它存储在 Key-Value 存储中并检索它。假设每个重复节点都有一个 UID。

  1. 生成一个对列表,其中键是 "XPATH",值是该叶子的实际值
  2. 应该可以assemble它变回xml
  3. xml 由 xsd 支持(是否有 JAXB 解决方案)

编辑并用更简单的 xml 替换了之前的

示例 xml 如下所示

<?xml version="1.0" encoding="UTF-8"?>
<cars>
    <car uid="WxiMr123">
        <carDoor uid="WRP2">
            <location uid="loc-1">
                <width uom="ft">2</width>
                <height uom="ft">3</height>
            </location>
            <location uid="loc-2">
                <width uom="m">5</width>
                <height uom="m">7</height>
            </location>
        </carDoor>
        <commonData>
            <timeCreated>2001-04-30T08:15:00.000Z</timeCreated>
        </commonData>        
    </car>    
</cars>

我正在查看的 xpath K、V 对应该类似于

/cars/car[@uid="WxiMr123"]@uid , "WxiMr123"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]@uid, "WRP2"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]@uid, "loc-1"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/width[@uom="ft"]@uom, "ft"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/width[@uom="ft"]/text(), "2"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/height[@uom="ft"]@uom, "ft"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/height[@uom="ft"]/text(), "3"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]@uid, "loc-2"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/width[@uom="m"]@uom, "m"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/width[@uom="m"]/text(), "5"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/height[@uom="m"]@uom, "m"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/height[@uom="m"]/text(), "7"
/cars/car[@uid="WxiMr123"]/commonData/timeCreated/text(), "2001-04-30T08:15:00.000Z"

非常感谢任何帮助。

制作所需文件并不难。例如,以下样式表:

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:for-each select="//text() | //@*[string()]">
        <xsl:for-each select="ancestor::*">
            <xsl:value-of select="concat('/', name())" />
                <xsl:for-each select="@*">
                    <xsl:value-of select="concat('[@', name(), '=&quot;', ., '&quot;]')" />
                </xsl:for-each>
        </xsl:for-each>
        <xsl:choose>
            <xsl:when test="name()">
                <xsl:value-of select="concat('/@', name())" />
            </xsl:when>
            <xsl:otherwise>/text()</xsl:otherwise>
        </xsl:choose>
        <xsl:value-of select="concat(', &quot;', ., '&quot;&#10;')" />
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

当应用于您的示例输入时,将产生以下 结果

/cars/car[@uid="WxiMr123"]/@uid, "WxiMr123"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/@uid, "WRP2"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/@uid, "loc-1"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/width[@uom="ft"]/@uom, "ft"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/width[@uom="ft"]/text(), "2"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/height[@uom="ft"]/@uom, "ft"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-1"]/height[@uom="ft"]/text(), "3"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/@uid, "loc-2"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/width[@uom="m"]/@uom, "m"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/width[@uom="m"]/text(), "5"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/height[@uom="m"]/@uom, "m"
/cars/car[@uid="WxiMr123"]/carDoor[@uid="WRP2"]/location[@uid="loc-2"]/height[@uom="m"]/text(), "7"
/cars/car[@uid="WxiMr123"]/commonData/timeCreated/text(), "2001-04-30T08:15:00.000Z"

:

  1. 这可能不是最有效的方法;对于大型 XMl 文档,应用 template/s 递归遍历整个树可能更好;

  2. 元素可以有多个属性;您的示例未显示在构建路径时如何处理这些问题;

  3. 元素可能在命名空间中;您的示例没有显示如何处理这些;

  4. 排除空节点;如果您尝试根据此转换的结果重建原始 XML 文档(我不知道该怎么做),这些节点将会丢失。