Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Line breaks (\n) via concat() in XPath?

Tags:

newline

xml

xpath

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>[email protected]</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>[email protected]</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>[email protected]</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>[email protected]</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>[email protected]</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?

like image 767
madcrazydrumma Avatar asked Dec 25 '22 07:12

madcrazydrumma


2 Answers

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.

like image 118
kjhughes Avatar answered Jan 01 '23 10:01

kjhughes


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
like image 27
zx485 Avatar answered Jan 01 '23 11:01

zx485