从xml文件中查询特定范围的行号

时间:2016-08-29 14:00:41

标签: xml shell

我想从行查询xml文件到1374-1601

我试过这个

$ sed -n '1374,1601p' *.xml | 
  xmlstarlet sel -t -v '//caldata[@chopper="on"]/c2[@unit="V/(nT*Hz)"]'

但我得到了

-:7.9: Extra content at the end of the document
        <caldata chopper="on" gain_1="0" gain_2="0" gain_3="0" impedance="(0,0)"
        ^

我的想法是选择行然后将这些行传递给xmlstartlet但是hat不起作用。

xml文件的一部分

<channel id="2">
  <calibration>
    <cal_version>1.0</cal_version>
    <creator>software chcal 1.2</creator>
    <user>metronix</user>
    <calibrated_item>
      <ci identifier="coil">MFS07e</ci>
      <ci_serial_number>252</ci_serial_number>
      <ci_revision/>
      <ci_date>2013-01-24</ci_date>
      <ci_time>10:57:24</ci_time>
      <ci_calibration_valid_until/>
      <ci_next_calibration/>
      <ci_tag/>
      <ci_owner/>
      <ci_owners_address/>
      <ci_manufacturer>metronix</ci_manufacturer>
      <ci_manufacturers_address>Kocher Str. 3, 38120 Braunschweig, Germany</ci_manufacturers_address>
      <ci_comments/>
    </calibrated_item>
    <calibration_equipment>
      <ce/>
      <ce_serial_number/>
      <ce_revision/>
      <ce_date/>
      <ce_time/>
      <ce_calibration_valid_until>1970-01-01</ce_calibration_valid_until>
      <ce_next_calibration/>
      <ce_tag/>
      <ce_operator/>
      <ce_location>Magnetsrode</ce_location>
      <ce_contact_address>Kocher Str. 3, 38120 Braunschweig, Germany</ce_contact_address>
      <ce_comments/>
    </calibration_equipment>
    <calibration_protocol>
      <mtx>
        <mtx_serial_numer_engraved/>
        <mtx_preamplifier_serialnumber/>
        <mtx_ch1_div_ch2_at_1000gain_0dot025_hz/>
        <mtx_phase_deg_at_1000gain_0dot025_hz/>
        <mtx_ch1_div_ch2_at_1000gain_0dot025_hz_calibrated/>
        <mtx_phase_deg_at_1000gain_0dot025_hz_calibrated/>
        <rec_freq_resp_at_0dot_0025_to_100_hz_at_gain_1000/>
        <rec_freq_resp_at_0dot_0025_to_100_hz_at_gain_100/>
        <rec_freq_resp_at_0dot_0025_to_100_hz_at_gain_10/>
        <rec_freq_resp_at_0dot_0025_to_100_hz_at_gain_1/>
        <gain_factor_preamplifier/>
        <actual_sensitivity_ch2_by_ch1/>
        <actual_sensitivity_theta/>
        <calibrated_sensitivity_ch2_by_ch1/>
        <calibrated_sensitivity_theta/>
        <calibrated_cal_path_ch2_by_ch1/>
        <calibrated_cal_path_theta/>
        <calibrated_chopper_on/>
        <calibrated_chopper_off/>
        <calibrated_chopper_ukn/>
      </mtx>
    </calibration_protocol>
    <caldata chopper="on" gain_1="0" gain_2="0" gain_3="0" impedance="(0,0)">
      <c0 unit="V">0.00000000e+00</c0>
      <c1 unit="Hz">4.00000000e-01</c1>
      <c2 unit="V/(nT*Hz)">1.93430000e-02</c2>
      <c3 unit="deg">8.92260000e+01</c3>
    </caldata>

我试图使用bichop的建议

xmlstarlet sel -t -v \
'//channel[@id="2"]/caldata[@chopper="on"]/c2[@unit="V/(nT*Hz)"]'

但它不起作用。

这是我的xml文件

http://pastebin.com/0BJTAMGV

2 个答案:

答案 0 :(得分:2)

答案结尾处的xmlstarlet命令存在一些问题,这意味着它永远不会起作用。查询的初始部分是......

//channel[@id="2"]/caldata[@chopper="on"]

...但是根据您的示例数据,这将永远不会匹配,因为channel元素没有任何caldata元素作为直接子元素。标签层次结构为:

channel
   calibration
     cal_version
     creator
     calibrated_item
     calibrated_equipment
     calibration_protocol
     caldata
     ...

所以你至少需要:

//channel[@id="2"]/calibration/caldata[@chopper="on"]

根据您的样本数据,如果我关闭所有未关闭的标签,我会得到:

$ xmlstarlet sel -t -v \
  '//channel[@id="2"]/calibration/caldata[@chopper="on"]' data.xml 
  0.00000000e+00
  4.00000000e-01
  1.93430000e-02
  8.92260000e+01

事实上,通过一次更正,您的整个查询似乎都有效:

$ xmlstarlet sel -t -v \
  '//channel[@id="2"]/calibration/caldata[@chopper="on"]/c2[@unit="V/(nT*Hz)"]' data.xml
1.93430000e-02

答案 1 :(得分:1)

如果您将文档剪切为以<channel id=2>开头,则必须以配对的</channel>结束才能仍然是有效文档。 (即使这样,如果其中一个父项包含xmlns=声明,您可能会以一种使其他有用查询无效的方式更改语义。)

由于您要查询的结束行不包含</channel>,因此您从文档中删除的子集无效且无法解析。

相应地调整行号,或 - 到目前为止更好的方法 - 调整查询以使用文档的语义来处理您想要的特定区域而不是行号范围