如何在 Go 的 xml struct tag 中表示备选项

huangapple go评论85阅读模式
英文:

How to represent alternates in a Go xml struct tag

问题

我正在尝试编写适当的结构标签来解析UCUM的XML版本。以下是unit标签的两个示例:

<unit Code="deg" CODE="DEG" isMetric="no" class="iso1000">
   <name>degree</name>
   <printSymbol>&#176;</printSymbol>
   <property>plane angle</property>
   <value Unit="[pi].rad/360" UNIT="[PI].RAD/360" value="2">2</value>
</unit>

<unit Code="[degF]" CODE="[DEGF]" isMetric="no" isSpecial="yes" class="heat">
   <name>degree Fahrenheit</name>
   <printSymbol>&#176;F</printSymbol>
   <property>temperature</property>
   <value Unit="degf(5 K/9)" UNIT="DEGF(5 K/9)">
      <function name="degF" value="5" Unit="K/9"/>
   </value>
</unit>

棘手的部分是value标签的内容,它可以是一个字符串(我会用字符串属性表示)或一个函数(这将需要一个自己的结构)。以下是我目前的代码:

type Unit struct {
	Code             string `xml:"Code,attr"`
	CodeCaps         string `xml:"CODE,attr"`
	IsMetric         bool   `xml:"isMetric,attr,omitempty"`
	IsSpecial        bool   `xml:"isSpecial,attr,omitempty"`
	Class            string `xml:"class,attr"`
	Name             string `xml:"name"`
    PrintSymbol      string `xml:"printSymbol,chardata"`
	DimensionTypeKey string `xml:"property,chardata"`
	Value            struct {
		Unit       string `xml:"Unit,attr"`
		UnitCaps   string `xml:"UNIT,attr"`
		Value      string `xml:"value,attr"`
		PrintValue string `xml:",chardata"`
        Function   struct { ... }
	} `xml:"value"`
}

如何准确描述这个XML结构的结构标签?

英文:

I'm trying to write the appropriate set of struct tags to parse the XML version of UCUM. Following are two examples of the unit tag:

&lt;unit Code=&quot;deg&quot; CODE=&quot;DEG&quot; isMetric=&quot;no&quot; class=&quot;iso1000&quot;&gt;
   &lt;name&gt;degree&lt;/name&gt;
   &lt;printSymbol&gt;&amp;#176;&lt;/printSymbol&gt;
   &lt;property&gt;plane angle&lt;/property&gt;
   &lt;value Unit=&quot;[pi].rad/360&quot; UNIT=&quot;[PI].RAD/360&quot; value=&quot;2&quot;&gt;2&lt;/value&gt;
&lt;/unit&gt;

&lt;unit Code=&quot;[degF]&quot; CODE=&quot;[DEGF]&quot; isMetric=&quot;no&quot; isSpecial=&quot;yes&quot; class=&quot;heat&quot;&gt;
   &lt;name&gt;degree Fahrenheit&lt;/name&gt;
   &lt;printSymbol&gt;&amp;#176;F&lt;/printSymbol&gt;
   &lt;property&gt;temperature&lt;/property&gt;
   &lt;value Unit=&quot;degf(5 K/9)&quot; UNIT=&quot;DEGF(5 K/9)&quot;&gt;
      &lt;function name=&quot;degF&quot; value=&quot;5&quot; Unit=&quot;K/9&quot;/&gt;
   &lt;/value&gt;
&lt;/unit&gt;

The tricky part is the contents of the value tag, which can either be a string (which I'd represent with a string attribute) or a function (which would require a struct of its own). Here's what I've got so far:

type Unit struct {
	Code             string `xml:Code,attr`
	CodeCaps         string `xml:CODE,attr`
	IsMetric         bool   `xml:isMetric,attr,omitempty`
	IsSpecial        bool   `xml:isEmptySpecial,attr,omitempty`
	Class            string `xml:class,attr`
	Name             string `xml:name`
    PrintSymbol      string `xml:printSymbol,chardata`
	DimensionTypeKey string `xml:property,chardata`
	Value            struct {
		Unit       string `xml:Unit,attr`
		UnitCaps   string `xml:UNIT,attr`
		Value      string `xml:Value,attr`
		PrintValue string `xml:,chardata`
        Function   struct { ... }
	} `xml:value`
}

How do I accurately describe this XML with struct tags?

答案1

得分: 1

你的代码几乎可以工作了;这是修复后的版本

基本上,你需要进行以下调整:

  • 在结构体标签中,值(即xml:前缀后的部分)必须用双引号括起来,像这样:

      `xml:"foo,attr"`
    
  • 当你只想获取元素标签之间的内容时,不需要指定,chardata

  • 要提取<function>元素,只需为其提供一个数据类型:解析器会提取它(如果存在)或者不提取(如果不存在)。

    要判断是否存在<function>元素,你可以检查PrintValue字段的值:如果它不全为空白字符,则表示没有<function>元素;否则表示有。

    或者,为解组这个元素定义一个单独的struct数据类型,并将其字段定义为指向该类型的指针,就像这样:

      type Function struct { ... }
      ...
      Function *Function `xml:"function"`
    

    这样,如果没有<function>元素,该字段的值将为nil,否则它将指向一个在堆上分配的Function实例。

英文:

Your code is almost working; here's the fixed version.

Basically you need the following adjustments:

  • In struct tags, the values&mdash;bits after the xml: prefix&mdash;must be enclosed in double quotes, like this:

      `xml:&quot;foo,attr&quot;`
    
  • There's no need to specify the ,chardata bit when you already just want to get whatever is between the element's tags.

  • To extract the &lt;function&gt; element just provide a data type for is: the parser will extract it if it's present or not if it's absent.

    To tell whether there was &lt;function&gt; or not, you can check the value of the PrintValue field: if it's not all-whitespace, there was no &lt;function&gt; element; otherwise there was.

    Alternatively, define a separate struct data type for unmarshaling this element, and have the field for it defined as a pointer to that type,
    like in

      type Function struct { ... }
      ...
      Function *Function `xml:&quot;function&quot;`
    

    This way, if there was no &lt;function&gt; element the field's value will be nil, otherwise it will point to a heap-allocated Function instance.

huangapple
  • 本文由 发表于 2016年3月15日 23:23:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/36015394.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定