douhoulei4706 2012-10-26 18:42
浏览 309
已采纳

使用xpath选择第一个结果的子项

I have a piece of XML where the same information can appear as a child of different nodes. Such as :

<root>
<category id=1>
        <product id="ABC123" >

              <sizes>
                    <size name="S"/>
                <size name="M"/>
                <size name="L"/>
                <size name="XL"/>
                <size name="2XL"/>
                <size name="3XL"/>
              </sizes>
            </product>

                 </products>
           </category>
<category id=2>
        <products>
        <product id="ABC123" >

              <sizes>
                    <size name="S"/>
                <size name="M"/>
                <size name="L"/>
                <size name="XL"/>
                <size name="2XL"/>
                <size name="3XL"/>
              </sizes>
            </product>

          <product id="PPP543" >

              <sizes>
                    <size name="S"/>
                <size name="M"/>
                <size name="L"/>
                <size name="XL"/>
              </sizes>
            </product>

                 </products>
           </category>

My goal is to select the sizes of product id ABC123 and store them as an array. The current code that I have is :

$arrTest=array();


    foreach($xml->xpath('//root/category/products/product[@id= "'.$productCall.'" ]/sizes/size') as $size){

              array_push($arrTest, $size["name"]);
      }

$productCall is the id I am looking for. In this case it's ABC123.

The output is S,M,L,XL,2XL,3XL,S,M,L,XL,2XL,3XL. Meaning that it is reading the two entries that were found. I expected this given the foreach loop, but I can't seem to find a way to just get the output of the first result. I have tried adding [0] and [1] :

$y=$xml->xpath('//root/category/products/product[@id= "'.$productCall.'" ][1]/sizes/size');

[0] returns nothing and [1] returns the same results I'm already getting.

I'm hoping this is a simple matter of me missing something something basic or just over-thinking, as I really haven't worked with xpath before.

  • 写回答

1条回答 默认 最新

  • duanjiangzhi6851 2012-10-26 18:49
    关注

    Use:

    (/*/*//product[@id='ABC123']/sizes)[1]/size
    

    Or use:

    ((/*/*/product | /*/*/products/product)/sizes)[1]/size
    

    XSLT - based verification:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="/">
      <xsl:copy-of select=
        "(/*/*//product[@id='ABC123']/sizes)[1]/size"/>
    ========
      <xsl:copy-of select=
        "((/*/*/product | /*/*/products/product)/sizes)[1]/size"/>
    
     </xsl:template>
    </xsl:stylesheet>
    

    When this transformation is applied to the provided XML document (after correcting it into a well-formed one):

    <root>
        <category id="1">
            <product id="ABC123" >
                <sizes>
                    <size name="S"/>
                    <size name="M"/>
                    <size name="L"/>
                    <size name="XL"/>
                    <size name="2XL"/>
                    <size name="3XL"/>
                </sizes>
            </product>
        </category>
        <category id="2">
            <products>
                <product id="ABC123" >
                    <sizes>
                        <size name="S"/>
                        <size name="M"/>
                        <size name="L"/>
                        <size name="XL"/>
                        <size name="2XL"/>
                        <size name="3XL"/>
                    </sizes>
                </product>
                <product id="PPP543" >
                    <sizes>
                        <size name="S"/>
                        <size name="M"/>
                        <size name="L"/>
                        <size name="XL"/>
                    </sizes>
                </product>
            </products>
        </category>
    </root>
    

    the two XPath expressions are evaluated and the selected nodes from each one, well visually delimited, are copied to the output -- both correct:

    <size name="S"/>
    <size name="M"/>
    <size name="L"/>
    <size name="XL"/>
    <size name="2XL"/>
    <size name="3XL"/>
    ========
      <size name="S"/>
    <size name="M"/>
    <size name="L"/>
    <size name="XL"/>
    <size name="2XL"/>
    <size name="3XL"/>
    

    Do note: I expect the second XPath expression to be more efficient (on sufficiently large documents), because it doesn't use the // pseudo-operator.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 spring后端vue前端
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题