【问题标题】:parse ACDSee categories解析 ACDSee 类别
【发布时间】:2015-06-17 08:20:01
【问题描述】:

如何解析类似 xml 的字符串并将其转换为单独的列表?

我正在尝试转换以下字符串:

<Categories>
  <Category Assigned="0">
    6 Level
    <Category Assigned="1">
      6.2 Level
      <Category Assigned="0">
        6.3 Level
        <Category Assigned="0">
          6.4 Level
          <Category Assigned="1">
            6.5 Level
          </Category>
        </Category>
      </Category>
    </Category>
  </Category>
</Categories>

到一个单独的列表,如:

6 Level/6.2 Level/6.3 Level/6.4 Level/6.5 Level, 6 Level/6.2 Level

exiv2 的 Robin Mills 提供了一个 perl 脚本: http://dev.exiv2.org/boards/3/topics/1912?r=1923#message-1923

这还需要解析Assigned="1"。如何在 C++ 中使用 digikam,在 dmetadata.cpp 内部使用如下结构:

    QStringList ntp = tagsPath.replaceInStrings("<Category Assigned="0">", "/");

我没有足够的编程背景来解决这个问题,也没有在网上找到任何类似的代码示例。我还想将代码包含在 exiv2 本身中,以便其他应用程序可以受益。

工作代码将包含在 digikam 中:https://bugs.kde.org/show_bug.cgi?id=345220

【问题讨论】:

  • Category 元素真的是这样嵌套的吗?这很不寻常
  • 很不寻常,是的。这就是 ACDSee 的工作方式。

标签: c++ kde4 exiv2


【解决方案1】:

您链接的代码使用了 Perl 的 XML::Parser::Expat 模块,它是 James Clark 的 Expat XML parser 之上的粘合层。

如果您想遵循相同的路线,您应该编写使用相同库的 C++,但使用 API 可能会很笨拙,因为 API 是通过您指定在传入 XML 流中的某些事件发生时调用的回调来实现的。您可以在 Perl 代码中看到它们,注释 process an start-of-element event 等。

链接到库后,编写与回调中的 Perl 等效的 C 代码应该很简单——它们只有一行。如果您在理解 Perl 时遇到问题,请打开一个新问题

另请注意,Expat 是一个非验证解析器,它允许不带注释的格式错误的数据通过

鉴于最大的任务首先是解析 XML 数据,您可能更喜欢一种不同的解决方案,该解决方案允许您从 XML 数据构建内存中的文档结构,并使用Document Object Model (DOM) 对其进行查询。 libxml 库允许您这样做,并且在 XML::LibXML 模块中有自己的 Perl 粘合层

【讨论】:

  • 我将更改问题以省略 perl 转换,因为它不是重要的部分。
  • @asp:嗯,好吧。但是的重要部分是什么?我认为可以链接到 Perl 代码以显示您需要的转换算法。但是,如果您的目标是在不参考 Perl 实现的情况下描述该算法,那么这可能是一个倒退,尤其是如果您不熟悉 Perl
  • 重要的部分是字符串转换,而不是perl例子。
  • 我认为解决方案保持不变:选择一个 XML 解析器库并编写一些代码,使用它来解析 XML 并提取文本节点
  • 谢谢@Borodin。我正在寻找做这种事情的例子。 digikam 的 Gilles 说应该可以使用 QstringList ...
【解决方案2】:

Maik Qualmann 为 digikam 提供了一个工作补丁!

QString xmlACDSee = getXmpTagString("Xmp.acdsee.categories", false);
if (!xmlACDSee.isEmpty())
{
    xmlACDSee.remove("</Categories>");
    xmlACDSee.remove("<Categories>");
    xmlACDSee.replace("/", "|");

    QStringList tagsXml = xmlACDSee.split("<Category Assigned");
    int category        = 0;
    int length;
    int count;

    foreach(const QString& tags, tagsXml)
    {
        if (!tags.isEmpty())
        {
            count  = tags.count("<|Category>");
            length = tags.length() - (11 * count) - 5;

            if (category == 0)
            {
                tagsPath << tags.mid(5, length);
            }
            else
            {
                tagsPath.last().append(QString("/") + tags.mid(5, length));
            }

            category = category - count + 1;

            if (tags.left(5) == QString("=\"1\">") && category > 0)
            {
                tagsPath << tagsPath.value(tagsPath.size() - count - 1);
            }
        }
    }

    if (!tagsPath.isEmpty())
    {
        return true;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多