xmlstarlet 将字符串 “null” 添加到自闭合标签中。

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

xmlstarlet add string "null" to self-closing tag

问题

我正在尝试从(Service-Now的REST API)返回的数据中创建一个sqlite3加载器,但它在其xml返回中使用了自闭标签。

如果我能将字段从空的自闭标签转换为带有新值“null”的开放和闭合对,那么我就可以解析该字符串,如果该字段是数组的一部分。

[ 当前 ]

```xml
# cat test.xml | xmllint --format -

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <result>
    <serial_number>
      <display_value>6W5QY03</display_value>
      <value>6W5QY03</value>
    </serial_number>
    <location>
      <display_value/>
      <value/>
    </location>
  </result>
</response>

[ 期望 ]

# cat test.xml | xmllint --format -

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <result>
    <serial_number>
      <display_value>6W5QY03</display_value>
      <value>6W5QY03</value>
    </serial_number>
    <location>
      <display_value>null<display_value/>
      <value>null<value/>
    </location>
  </result>
</response>

已经做了很多搜索,但是使用(sed)等实用工具进行替换我认为不是正确的方法。

如果我不能放置一些东西在那里,我就不能测试它。如果返回可能包含许多正面的结果,测试状态是否失败将不起作用。

# cat test.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <response>
      <result>
        <serial_number>
          <display_value>6W5QY03</display_value>
          <value>6W5QY03</value>
        </serial_number>
        <location>
          <display_value/>
          <value/>
        </location>
      </result>
    </response>

# xmlstarlet sel -T -t -v "response/result/location/display_value/text()" test.xml

# echo $?
1

# xmlstarlet sel -T -t -v "response/result/serial_number/display_value/text()" test.xml
6W5QY03
# echo $?
0
英文:

I am trying to create an sqlite3 loader from data returned from ( Service-Now's REST API ) but it uses self closing tags in it's xml return.

If I could convert the fields from empty self closing to an opening and closing pair with a new value of "null" then I could parse the string if the field was part of an array.

[ CURRENT ]

# cat test.xml | xmllint --format -

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <result>
    <serial_number>
      <display_value>6W5QY03</display_value>
      <value>6W5QY03</value>
    </serial_number>
    <location>
      <display_value/>
      <value/>
    </location>
  </result>
</response>

[ DESIRED ]

# cat test.xml | xmllint --format -

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <result>
    <serial_number>
      <display_value>6W5QY03</display_value>
      <value>6W5QY03</value>
    </serial_number>
    <location>
      <display_value>null<display_value/>
      <value>null<value/>
    </location>
  </result>
</response>

Have done a lot of searching but substitution with utilities like ( sed ) I don't think is the way to go.

If I can't put something there I can't test for it. If the return could contain many positive returns one failure testing for status would not work.

# cat test.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <response>
      <result>
        <serial_number>
          <display_value>6W5QY03</display_value>
          <value>6W5QY03</value>
        </serial_number>
        <location>
          <display_value/>
          <value/>
        </location>
      </result>
    </response>

# xmlstarlet sel -T -t -v "response/result/location/display_value/text()" test.xml

# echo $?
1

# xmlstarlet sel -T -t -v "response/result/serial_number/display_value/text()" test.xml
6W5QY03
# echo $?
0

答案1

得分: 1

你可以在 xmlstarlet 中使用 xslt,例如使用以下 xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output indent="yes"/>

  <xsl:strip-space elements="*"/>

  <!-- 默认复制模板 -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <!-- 
    匹配没有子节点的元素的模板:text() 和 element() 都是节点
  -->
  <xsl:template match="*[not(node())]">
    <xsl:copy>
      <xsl:text>null</xsl:text>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
英文:

You could use xslt in xmlstarlet i.e. with this xslt:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;xsl:stylesheet xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot;&gt;
  
  &lt;xsl:output indent=&quot;yes&quot;/&gt;
  
  &lt;xsl:strip-space elements=&quot;*&quot;/&gt;
  
  &lt;!-- Default copy template --&gt;
  &lt;xsl:template match=&quot;node()|@*&quot;&gt;
    &lt;xsl:copy&gt;
      &lt;xsl:apply-templates select=&quot;node()|@*&quot;/&gt;
    &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- 
    Template that matches a element that has no node(): 
    text() en element() are both nodes
  --&gt;
  &lt;xsl:template match=&quot;*[not(node())]&quot;&gt;
    &lt;xsl:copy&gt;
      &lt;xsl:text&gt;null&lt;/xsl:text&gt;
    &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;

&lt;/xsl:stylesheet&gt;

答案2

得分: 1

以下xmlstarlet命令实现您的需求。ed选项用于1)查找所有没有任何内容的元素,2)将文本“null”添加到它们中。

xmlstarlet ed -u "//*[not(node())]" -v "null" test.xml

请注意,这不仅捕获自闭合元素;它捕获所有空元素。从XML的角度来看,&lt;x/&gt;&lt;x&gt;&lt;/x&gt;是等价的。

英文:

The following xmlstarlet command does what you want. The ed option is used to 1) find all elements that don't have any content and 2) add the text "null" to them.

xmlstarlet ed -u &quot;//*[not(node())]&quot; -v &quot;null&quot; test.xml

Note that this does not capture just self-closing elements; it captures all empty elements. From an XML point of view, &lt;x/&gt; and &lt;x&gt;&lt;/x&gt; are equivalent.

huangapple
  • 本文由 发表于 2023年7月23日 18:39:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76747794.html
匿名

发表评论

匿名网友

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

确定