【问题标题】:xml to json, is there a way to use an attribute's value as a key for easier lookup?xml 到 json,有没有办法使用属性的值作为更容易查找的键?
【发布时间】:2019-07-17 16:58:12
【问题描述】:

我有一个包含多个项目的 XML 文件,我尝试了几个 xml 到 json 库并选择了 csv-parser。 现在如果我想在转换之前检查对象是否满足我想要的要求,我需要循环遍历项目,然后循环遍历属性标签以查看是否可以找到属性 DisplayType 然后检查它的值。

有没有办法告诉 csv-parser 使用“name”属性作为对象的 ID?

有时我有 5 个 for 循环,这变得令人困惑。

编辑: 主要目标是过滤 property[@name='DisplayType'] 值为 Weapon 的项目,遍历这些项目并做一些事情。然后对其他属性和属性进行筛选并重复。

我需要在插入数据库之前过滤、排列和添加数据。

“原始”:

<items>
    <item name="Knife">
        <property name="HoldType" value="31"/>
        <property name="DisplayType" value="Weapon"/>
        <property name="Meshfile" value="Items/Misc/parcelPrefab"/>
        <property name="Material" value="MresourceCrop"/>
        <property name="Stack" value="10"/> 
        <property name="Value" value="3"/>
        <events>
                <event name="Testing Events" type="Something"/>
                <event name="Testing Events2" type="Something"/>
        </events>
    </item>
    <item name="Knife">
        <property name="HoldType" value="31"/>
        <property name="DisplayType" value="Weapon"/>
        <property name="Meshfile" value="Items/Misc/parcelPrefab"/>
        <property name="Material" value="MresourceCrop"/>
        <property name="Stack" value="10"/> 
        <property name="Value" value="3"/>
    </item>
</items>

Json(示例):

{
    "items": {
        "item": [
            {
                "name": "Knife",
                "property": [
                    {
                        "name": "HoldType",
                        "value": "31"
                    },
                    {
                        "name": "DisplayType",
                        "value": "Weapon"
                    },
                    {
                        "name": "Meshfile",
                        "value": "Items/Misc/parcelPrefab"
                    },
                    {
                        "name": "Material",
                        "value": "MresourceCrop"
                    },

我希望我能得到什么:

{
    "items": {
            "Knife": {
                "name": "Knife",
                "property": [
                    "HoldType": {
                        "name": "HoldType",
                        "value": "31"
                    },
                    "DisplayType": {
                        "name": "DisplayType",
                        "value": "Weapon"
                    },
                    "Meshfile": {
                        "name": "Meshfile",
                        "value": "Items/Misc/parcelPrefab"
                    },
                    "Material": {
                        "name": "Material",
                        "value": "MresourceCrop"
                    },

【问题讨论】:

  • 您是否必须将您的 xml 转换为 JSON,或者您可以在原始文件上使用 xpath 之类的东西吗?
  • @JackFleeting 哦,这个库没有出现在我的搜索中!我会试一试,它一定比处理怪异的 JSON 更容易:P 如果您想快速回答如何查询 XML 文件,我将标记为已回答。
  • 在这种情况下您想要的输出是单词weapon吗?
  • 是的,我希望能够获取 DisplayType == Weapon 的项目。我现在正在玩图书馆,但我现在正在阅读源代码,试图弄清楚它是如何工作的。
  • 只是要清楚 - 在你的例子中 DisplayType 不是 == Weapon;两个相关节点是property,每个节点都有一个name 属性,其值为DisplayType 和一个value 属性,其值为Weapon。这就是将这两个节点与具有相同名称和属性但属性值不同的其他节点区分开来的原因。那么要选择这两个节点吗?

标签: node.js xml-parsing


【解决方案1】:

你可以试试这个

const { transform } = require('camaro')

;(async function () {
    const xml = `
    <items>
        <item name="Knife">
            <property name="HoldType" value="31"/>
            <property name="DisplayType" value="Weapon"/>
            <property name="Meshfile" value="Items/Misc/parcelPrefab"/>
            <property name="Material" value="MresourceCrop"/>
            <property name="Stack" value="10"/> 
            <property name="Value" value="3"/>
            <events>
                    <event name="Testing Events" type="Something"/>
                    <event name="Testing Events2" type="Something"/>
            </events>
        </item>
        <item name="Knife">
            <property name="HoldType" value="31"/>
            <property name="DisplayType" value="Weapon"/>
            <property name="Meshfile" value="Items/Misc/parcelPrefab"/>
            <property name="Material" value="MresourceCrop"/>
            <property name="Stack" value="10"/> 
            <property name="Value" value="3"/>
        </item>
    </items>
    `

    const template = {
        items: {
            Knife: ['/items/item[@name="Knife"]', {
                Name: '@name',
                HoldType: 'property[@name="HoldType"]/@value',
                DisplayType: 'property[@name="DisplayType"]/@value',
                Meshfile: 'property[@name="Meshfile"]/@value',
                Material: 'property[@name="Material"]/@value',
                Stack: 'property[@name="Stack"]/@value',
                Value: 'property[@name="Value"]/@value',
            }]
        }
    }

    const result = await transform(xml, template)

    console.log(JSON.stringify(result, null, 2))
})()

输出

【讨论】:

  • 我喜欢这个解决方案!这很清楚也很容易。感谢那!!
【解决方案2】:

xpath 表达式

/items/item/property[@name="DisplayType"][@value="Weapon"]

或其等价物

/items/item/property[@name="DisplayType" and @value="Weapon"]

将在您的示例中选择具有所需属性值的两个节点。

【讨论】:

  • 谢谢,我可以得到它的父母吗?现在它返回 15 个结果,所有相同的行:P 我在最后尝试了/parent::store,就像规范一样,但我猜图书馆有另一种方法。
  • Nm, //items/item/property[@name="DisplayType"][@value="Weapon"]/parent::item :) 谢谢你让我开始做这个。
  • @HypeWolf - 在您的 xml 中没有 store;这两个节点的父节点是item,具有name 属性,其属性值为Knife,祖父节点是items。没有属性。
  • 是的,我犯了不阅读和复制/粘贴的错误……我不知道今天发生了什么。 :P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 2015-04-25
  • 2011-06-02
相关资源
最近更新 更多