【问题标题】:How can I get the content of the subfield with batch script?如何使用批处理脚本获取子字段的内容?
【发布时间】:2016-12-12 17:55:01
【问题描述】:

我有以下 xml:

<datafield tag="007G">
    <subfield code="c">GBV</subfield>
    <subfield code="0">688845614</subfield>
  </datafield>

我尝试提取&lt;subfield code="0" 688845614的内容

这是我的代码:

@echo off
for /F "tokens=2 delims=>/<" %%i in ('findstr "007G" curlread.txt') do echo %%i
pause

但作为输出我只得到&lt;datafield tag="007G"&gt;

xml 文档中可能有很多&lt;datafield tag="007G"&gt;,我需要从每个文档中获取&lt;subfield code="0"

【问题讨论】:

  • 如果你对&lt;subfield code="0"&gt;感兴趣,那你为什么要搜索007G呢?无论如何,我建议不要为此使用批处理文件,因为它本身不理解 XML 文件;而是使用可以处理 XML 文件的语言......
  • 批处理无法解析 XML,findstr 只返回与您搜索的内容匹配的行。
  • Vbscript、Jscript 和 Powershell 都具有原生读取 XML 文件的能力。

标签: xml batch-file extraction


【解决方案1】:

将结构化标记语言解析为分层数据总是更好,而不是作为平面文本进行抓取。

要仅从第一个 &lt;subfield code="0"&gt; 节点返回数据,请将您的 findstr 命令替换如下:

powershell "([xml](gc curlread.txt)).selectSingleNode('//subfield[@code=0]/text()').data"

如果您将有多个 &lt;subfield code="0"&gt; 节点并且您想要来自所有节点的数据,那么

powershell "([xml](gc curlread.txt)).selectNodes('//subfield[@code=0]/text()') | %%{ $_.data }"

XPath 的胜利。您还可以通过像这样修改 XPath 选择器来仅指定作为 &lt;datafield tag="007G"&gt; 子级的 &lt;subfield code="0"&gt; 节点:

//datafield[@tag=\"007G\"]/subfield[@code=0]/text()

重要提示: XPath 中的引号必须用反斜杠转义。


编辑:鉴于您在下面的评论中粘贴的 XML:

<datafield tag="007G">
    <subfield code="c">GBV</subfield>
    <subfield code="0">688845614</subfield>
</datafield>
<datafield tag="008G">
    <subfield code="c">GBV</subfield>
    <subfield code="0">68614</subfield>
</datafield>

... 请注意,这不是完全有效的 XML。有效的 XML 有一个层次结构根。在解析数据之前,您必须用根标记将其括起来。

这是一个如何做到这一点的示例:

@echo off & setlocal

set "xml=curlread.xml"
rem // Note that quotation marks in the XPath must be backslash escaped
set "xpath=//datafield[@tag=\"007G\"]/subfield[@code=0]/text()"

for /f "delims=" %%I in (
    'powershell "([xml]('<r>{0}</r>' -f (gc %xml%))).selectNodes('%xpath%') | %%{$_.data}"'
) do (
    set "subfield=%%I"

    setlocal enabledelayedexpansion
    echo something useful with !subfield!
    endlocal
)
pause
goto :EOF

【讨论】:

  • 我总是只得到“+”符号作为输出。不明白出了什么问题
  • @OlegNekhayenko 可能是 PowerShell 错误消息。也许您的 XML 文件不完全有效?或者您的 XPath 选择器可能与任何节点都不匹配,因此 PowerShell 在尝试访问不存在的 .data 属性时会阻塞?尝试直接从控制台运行powershell "([xml](gc curlread.txt)).selectSingleNode('//subfield[@code=0]/text()').data" 命令,看看您是否可以阅读完整的错误消息。
  • 我只运行了powershell位,问题确实是powershell错误消息,即xml文件的路径错误。下一个问题是现在我没有得到任何输出,甚至没有错误消息。
  • PS C:\Users\NekhayenkoO\Desktop\CDSSkript&gt; ([xml](gc curlread.xml)).selectSingleNode('//datafieldasdfasdf[@tag="007G"]/subfield[@code=0]/text()').data 尽管有一个显然是无意义的 xpath,但它不会产生任何输出。您对如何使调用更详细有任何想法吗?
  • @OlegNekhayenko 如果 PowerShell sn-p 的结果是一个空字符串,那么 for /f 循环将无法定义 %subfield%。因此,在set "subfield=%%I" 之后的行中,只需执行if not defined subfield echo No results found 或任何您认为合适的操作。或者,您可以将脚本重写为 Batch + PowerShell hybrid script,在 PowerShell 单行代码之前为您提供任意数量的附加逻辑。或者您可以在 PowerShell 中编写整个内容。或 JScript 或 VBScript。
猜你喜欢
  • 2021-11-14
  • 1970-01-01
  • 2013-07-30
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 2011-08-06
  • 2018-06-23
  • 2011-06-15
相关资源
最近更新 更多