如何将嵌套字符串(元数据)包装到 TagGroup 中

How to wrap nested string (metadata) into TagGroup

我导入的元数据有一个预定义的嵌套结构(示例如下所示),导入到DM后是一个字符串。 整个元数据和每个分支级别都包含在大括号 {} 中,所有键和键值都包含在引号 "" 中并以冒号分隔:

我的问题是,如何转换数据并将它们包装到 TagGroup 对象中,以便更轻松地进行索引、搜索和数据访问操作?

谢谢!

这是一个例子:

{
    "Acquisition": {
        "AcquisitionStartDatetime": {
            "DateTime": "1473763749"
        },
        "AcquisitionDatetime": {
            "DateTime": "0"
        },
        "BeamType": "",
        "SourceType": "Monochromator"
    },
    "BinaryResult": {
        "AcquisitionUnit": "",
        "CompositionType": "",
        "DetectorIndex": "3",
        "Detector": "HAADF",
        "PixelSize": {
            "width": "5.408370946750477e-010",
            "height": "5.408370946750477e-010"
        },
        "PixelUnitX": "m",
        "PixelUnitY": "m",
        "Offset": {
            "x": "-2.769085924736244e-007",
            "y": "-2.769085924736244e-007"
        },
        "Encoding": ""
    },
    "Sample": "",
    "GasInjectionSystems": ""
}

正如迈克在评论中指出的那样,这是一项繁琐而不是困难的任务。最好在单独的 class 中创建一个小的解析器脚本来转换格式

"NAME: { 到标签 NAME 的 TagGroups 加上增加的层次结构级别。

"NAME": "VALUE" 到标签 NAME 和值 VALUE 的 Tags

} 进入 'reduce hierachy level' 步。

请注意,您始终可以在创建标签组时使用字符串,即使您想在稍后的时间点将其作为数字读出。

递归浏览并记住您所在的 "taggroup-level",以便在该级别添加每个新标签。跳过无效的文本部分。

DigitalMicrograph 的 F1 帮助文档有一个关于字符串的部分,其中列出了您最可能需要的命令:

String StringAppend( String s1, String s2 ) 
Number StringCompare( String s1, String s2 ) 
Boolean StringIsValid( String str ) 
String StringToLower( String str ) 
String StringToUpper( String str ) 
Number len( String str )
String left( String str, Number count )
String mid( String str, Number offset, Number count )
String right( String str, Number count )
Number find( String s1, String s2 )
Number val( String str )

此外,我发现有时对像

这样的字符串使用叔运算符很有用
number isOK = 1
string str =  isOK == 1 ? "true" : "false"

此外,在解析时,请注意制表符和行 return 字符。 (使用 \t 和 \n 搜索它们。在字符串中指定 int 时可能需要使用“\n”和“\t”,因为 \ 将被解释为控制字符。)

编辑:现在修正代码

我确定可以使用更简洁的版本,但它可以完成任务:

Class CMetaStringToTagGroup
{
    // Find next string bracketed by " in input string, starting search
    // at given index. Returns string and end-position of search
    string FindNextKeyName( object self, string input, number & searchPos )
    {
        number totalLength = len( input )
        number start = 0, end = 0
        while( searchPos < totalLength )
        {
            searchpos++
            if ( "\"" == input.mid(searchpos-1,1) )
            {
                if ( !start ) 
                    start = searchpos-1
                else
                    {
                    end = searchpos-1
                    return input.mid(start+1,end-start-1)
                    }
            }
        }
        return ""
    }

    // Returns the next of either "{" ,  "}" or """ after a collon ":"
    string GetNextIndicator( object self, string input, number & searchPos )
    {
        number totalLength = len( input )
        while( searchPos < totalLength )
        {
            searchpos++        
            if ( "{" == input.mid(searchpos-1,1) )
                return "{"
            if ( "}" == input.mid(searchpos-1,1) )
                return "}"
            if ( "\"" == input.mid(searchpos-1,1) )
                return "\""
        }
        return ""
    }

    // In a tag-path string, find location of last colon 
    number findLastColon( object self, string input )
    {
        number totalLength = len( input )
        number lastPos = -1
        number searchPos = 0
        while( searchPos < totalLength )
        {
            searchpos++
            if ( ":" == input.mid(searchpos-1,1) )
                lastPos = searchpos-1
        }
        return lastPos
    }

    // Parse textstring and create taggroup from it
    TagGroup CreateTagFromText( object self, string input )
    {
        TagGroup rootTG = NewTagGroup()
        string currentPath = ""

        number totalLength = len( input )
        number searchPos = 0 
        number searchPos2
        string keyName, indicator
        while( searchPos < totalLength )
        {
            // search for new key or closing bracket, whatever first 
            searchPos2 = searchPos
            indicator = self.GetNextIndicator( input, searchPos2 )
            keyName = self.FindNextKeyName( input, searchPos )
            if ( ( "}" == indicator ) && (searchpos2<searchPos ) )
            {
                // decrease hierachy
                number cutPos = self.findLastColon( currentPath )
                currentPath = left( currentPath, cutPos )
                result("\n DEC ")
                searchPos = searchPos2
            }
            else
            {
                // Either add value or new  sub-tagGroup
                if ( "" == keyname ) break; // No more keys found
                indicator = self.GetNextIndicator( input, searchPos )
                if ( "" == indicator ) break;   // No more indicator found -- should not happen!

                if ( "{" == indicator )
                {
                    // increase hierachy
                    currentPath += ":" + keyname
                    rootTg.TagGroupSetTagAsTagGroup( currentPath, NewTagGroup() )
                    result("\n INC ("+keyname+")")
                }
                else if ( "\"" == indicator )
                {
                    // Add value
                    searchPos--
                    string valStr = self.FindNextKeyName( input, searchPos )
                    rootTg.TagGroupSetTagAsString( currentPath + ":" + keyname, valStr )
                    result("\n   VAL("+keyname+") ")
                }
            }
        }
        return rootTg
    }
}

{
    // Reading input text
    number fileID = OpenFileForReading("C:\test.txt")
    object fStream = NewStreamFromFileReference(fileID,1)
    string inputStr = fStream.StreamReadAsText(0, fStream.StreamGetSize())

    // Parsing text
    number searchPos = 0
    TagGroup con = alloc(CMetaStringToTagGroup).CreateTagFromText( inputStr )
    con.TagGroupopenBrowserwindow("",0)
}