5

So I have an XML document of employees in my system:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<couriersystem title="System"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="schema.xsd">
    <!-- snip -->
    <employees>
        <employee eid="1">
            <nin>AZ123518D</nin>
            <firstname>Peter</firstname>
            <lastname>Smith</lastname>
            <gender>Male</gender>
            <dob>1994-02-11</dob>
            <email>ps11@gmail.com</email>
            <address>
                119, London Street, Nidrie, F57 8NE
            </address>
            <tel>07005748900</tel>
            <salary>30526</salary>
            <empbranch bid="1" />
            <supervisor sid="1" />
        </employee>
        <employee eid="2">
            <nin>CN174869F</nin>
            <firstname>Jennifer</firstname>
            <lastname>Black</lastname>
            <gender>Male</gender>
            <dob>1984-12-24</dob>
            <email>jb21@gmail.com</email>
            <address>
                161, South Road, Nidrie, W79 8WG
            </address>
            <tel>07555111222</tel>
            <salary>40576</salary>
            <empbranch bid="2" />
            <supervisor sid="1" />
        </employee>
        <employee eid="3">
            <nin>ET127654M</nin>
            <firstname>Aaron</firstname>
            <lastname>Jones</lastname>
            <gender>Male</gender>
            <dob>1968-03-15</dob>
            <email>aj31@gmail.com</email>
            <address>
                66, High Road, Yoker, Q47 4SR
            </address>
            <tel>07856471267</tel>
            <salary>30526</salary>
            <empbranch bid="3" />
            <supervisor sid="1" />
        </employee>
        <employee eid="4">
            <nin>GC765238A</nin>
            <firstname>Alistair</firstname>
            <lastname>Smith</lastname>
            <gender>Male</gender>
            <dob>1976-11-26</dob>
            <email>as11@gmail.com</email>
            <address>
                109, West Plaza, Clydebank, G55 8RC
            </address>
            <tel>07000123123</tel>
            <salary>25400</salary>
            <empbranch bid="4" />
            <supervisor sid="1" />
        </employee>
        <employee eid="5">
            <nin>HP146854D</nin>
            <firstname>Emma</firstname>
            <lastname>Reynolds</lastname>
            <gender>Male</gender>
            <dob>1995-05-05</dob>
            <email>er11@yahoo.com</email>
            <address>
                57, Scott Street, Aberdeen, O75 2KS
            </address>
            <tel>07625361536</tel>
            <salary>25400</salary>
            <empbranch bid="5" />
            <supervisor sid="7" />
        </employee>
        <!-- snip -->
    </employees>
    <!-- snip -->
</couriersystem>

And I have the following XPath to retrieve all of the employee details by their supervisor:

//employee[supervisor/@sid='1']/concat('Name: ', concat(firstname/text(), ' ', lastname/text(), '\nGender: ', gender/text(), '\nD.O.B: ', dob/text()))

But it only shows one employee out of the rest of them, and the \n characters show as well.

How can I fix this issue?

kjhughes
  • 98,039
  • 18
  • 159
  • 218
madcrazydrumma
  • 1,817
  • 3
  • 18
  • 35

2 Answers2

9

To get \n to be interpreted in concat() in XPath, use codepoints-to-string(10) [credit: @madcrazydrumma]:

//employee[supervisor/@sid='1']/concat('Name: ', firstname, ' ', lastname, 
                                       codepoints-to-string(10),
                                       'Gender: ', gender, 
                                       codepoints-to-string(10),
                                       'D.O.B: ', dob)

which will then return results as follows:

Name: Peter Smith
Gender: Male
D.O.B: 1994-02-11
Name: Jennifer Black
Gender: Male
D.O.B: 1984-12-24
Name: Aaron Jones
Gender: Male
D.O.B: 1968-03-15
Name: Alistair Smith
Gender: Male
D.O.B: 1976-11-26

Minor note: Your basic XPath 2.0 expression turned out to be fine. As we discovered in the comments, the results were incorrect due to limitations of the site, xpathtester.com/xpath. Use videlibri.sourceforge.net/cgi-bin/xidelcgi instead for online XPath 2.0 testing.

Community
  • 1
  • 1
kjhughes
  • 98,039
  • 18
  • 159
  • 218
  • Its only returning one result though, which is the strangest thing! – madcrazydrumma Mar 30 '16 at 15:57
  • What XPath 2.0 library are you using? – kjhughes Mar 30 '16 at 15:58
  • 1
    I've seen such problems with that site's XPath 2.0 implementation. Try this site instead: http://videlibri.sourceforge.net/cgi-bin/xidelcgi – kjhughes Mar 30 '16 at 16:06
  • @kjhuges that solves the issue! But how can i use new lines? – madcrazydrumma Mar 30 '16 at 16:10
  • I used `codepoints-to-string(10)` to add a new line in XPath 2.0. You can update your code if you like to show others, thank you for the new site! – madcrazydrumma Mar 30 '16 at 16:25
  • How do you check your version of XPath? – Yzmir Ramirez Dec 20 '20 at 06:34
  • @YzmirRamirez: There is no XPath standard way to determine the version of an XPath implementation. See the general probe technique given in my answer to [Does Chrome use XPath 2.0](https://stackoverflow.com/q/25455351/290085). (Web browsers only support 1.0 currently (with no signs of advancing)). – kjhughes Dec 20 '20 at 15:14
  • 1
    I was flailing around trying to figure out how to detect an XML element containing line breaks and this was the first mention of codepoints-to-string() I've seen; thank you! All my attempts to specify '\n' or '\r' weren't working. But this worked perfectly for me in Altova XMLSpy: `/PNRList/PNR/SegmentList/HotelSegment/Address[contains(text(), codepoints-to-string(10))]` – ALEXintlsos Mar 08 '22 at 17:09
3

Well, I tested your XPath expression with XSLT and the output contains 4 entries as you desired:

My XSLT was:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/couriersystem">
    <xsl:copy-of select="//employee[supervisor/@sid='1']/concat('Name: ', concat(firstname/text(), ' ', lastname/text(), '\nGender: ', gender/text(), '\nD.O.B: ', dob/text()))" />
  </xsl:template>
</xsl:stylesheet>

The result is all in one line of text:

<?xml version="1.0" encoding="UTF-8"?>Name: Peter Smith\nGender: Male\nD.O.B: 1994-02-11 Name: Jennifer Black\nGender: Male\nD.O.B: 1984-12-24 Name: Aaron Jones\nGender: Male\nD.O.B: 1968-03-15 Name: Alistair Smith\nGender: Male\nD.O.B: 1976-11-26

If you like to have the output a little bit more formatted than the above, try this expressions which inserts space characters at the appropriate places:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/couriersystem">
    <xsl:value-of select="'&#10;'" />
    <xsl:for-each select="//employee[supervisor/@sid='1']">
      <xsl:value-of select="concat('Name: ', firstname/text(), ' ', lastname/text(), '&#10;','Gender: ', gender/text(), '&#10;','D.O.B: ', dob/text(),'&#10;')" />
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

The result of this is:

<?xml version="1.0" encoding="UTF-8"?>
Name: Peter Smith
Gender: Male
D.O.B: 1994-02-11
Name: Jennifer Black
Gender: Male
D.O.B: 1984-12-24
Name: Aaron Jones
Gender: Male
D.O.B: 1968-03-15
Name: Alistair Smith
Gender: Male
D.O.B: 1976-11-26

P.S.: Is 'Jennifer Black' a transsexual? Because she has a female name and a male gender ;-)

zx485
  • 26,827
  • 28
  • 51
  • 55
  • Haha my friend input the data so maybe! ;) and I'm not using XSL for this, so that unfortunately doesn't solve the issue – madcrazydrumma Mar 30 '16 at 16:08
  • 1
    Well, my last remark was just a little joke *g*. However, my XPath expression is basically identical to the accepted answer, just replace ` ` with `codepoints-to-string(10)` and merge the expressions and your done. – zx485 Mar 30 '16 at 17:00