【问题标题】:Retrieving a text string from a xml document从 xml 文档中检索文本字符串
【发布时间】:2022-11-24 05:12:14
【问题描述】:

我正在尝试检索属于text id="short_name 的字符串“This is my string”

我努力了:

$SVGTemplate          = Get-Content "C:\temp\sample.svg
$SVGTemplate          = [XML]$SVGTemplate
$SVGTemplateShortName = Select-Xml -Xml $SVGTemplate -XPath '/s:svg/s:g/s:g[@id="short_name"]/s:text/text()' -Namespace @{s = "http://www.w3.org/2000/svg"}
$SVGTemplateShortName.node.value

但它返回一个空值。这以前有用,但最近坏了,因为我不得不重新设计 svg 图形。

我多次尝试更正 XPath,但它一直返回一个空值。我做错了什么? 下面是我的 xml 文件。

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
<style type="text/css">
    .st0{fill:#E30613;}
    .st1{fill:#FFFFFF;}
    .st2{fill:#009FE3;}
    .st3{fill:none;}
    .st4{font-family:'MyriadPro-Regular';}
    .st5{font-size:88px;}
    .st6{fill:#008D36;}
</style>
<g id="background">
    <rect id="stroke" class="st0" width="500" height="500"/>
    <rect id="Fill" x="12" y="12" class="st1" width="476" height="476"/>
</g>
<g id="short">
    <rect id="short_fill" x="12" y="400" class="st2" width="476" height="100"/>
    <rect y="412" class="st3" width="500" height="88"/>
    <text id="short_name" transform="matrix(1 0 0 1 87.7305 474.4795)" class="st1 st4 st5">This is my string</text>
</g>
<g id="hud">
    <rect id="left" x="12" y="12" class="st6" width="92" height="76"/>
    <rect id="right" x="396" y="12" width="92" height="76"/>
</g>
<g id="graphic">
    <g id="Card_Symbl">
        <g id="Layer_10">
            <polygon class="st0" points="309.9,387.1 396.3,124.5 303.1,105.8 96.5,251.1             "/>
        </g>
    </g>
</g>
</svg>

【问题讨论】:

    标签: powershell


    【解决方案1】:

    如果要通过完整路径定位元素,更简单的方法是使用 PowerShell 的成员访问:

    $SVGTemplate.svg.g.text | Where-Object id -eq 'short_name' | ForEach-Object '#text'
    

    ...或更简洁,使用内在的.Where方法:

    $SVGTemplate.svg.g.text.Where{ $_.id -eq 'short_name'}.'#text'
    

    如果您想定位一个元素而不管它嵌套的深度有多深(相对路径,由双斜线引入),XPath 确实有优势:

    $SVGTemplate | 
        Select-Xml -XPath '//s:text[@id="short_name"]' -Namespace @{s = "http://www.w3.org/2000/svg"} | 
        ForEach-Object { $_.Node.'#text' }
    

    当然,它也可以使用绝对路径(使用单斜杠引入),但比它的成员访问副本要长得多:

    $SVGTemplate | 
        Select-Xml -XPath '/s:svg/s:g/s:text[@id="short_name"]' -Namespace @{s = "http://www.w3.org/2000/svg"} | 
        ForEach-Object { $_.Node.'#text' }
    

    【讨论】:

      【解决方案2】:

      原始 XPath 需要一个带有 id 属性和值“short_name”的 &lt;g&gt; 标记……但是 XML 不包含这样的路径。它应该读作 `/s:text[@id="short_name"] 吗?

      除此之外,是的,任何人都可以使用 PS 的“人性化”访问方法……尽管当没有附加到 XML 的模式或尝试访问可能或可能的可选节点时,存在一些固有的危险对于给定的路径可能不存在。

      PS 适用于列表。使用 $xmlDoc.tagA.tagB.tagC 表示法时 XML 路径中断;假设这不是 $null 并且是一个长于恰好一 (1) 个节点的列表,那么我们无法判断在 XML 中的位置以及可能在什么条件下我们从中获取了这些节点。

      ... 当有疑问时:不要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-24
        • 2011-02-03
        • 1970-01-01
        • 2013-03-19
        • 2019-04-14
        相关资源
        最近更新 更多