XPATH or XSL to map two node networks using custom comparison

EDIT: I also have access to ESXLT features .

I have two node string tone sets. One set contains the following values:

/Geography/North America/California/San Francisco
/Geography/Asia/Japan/Tokyo/Shinjuku

Another set contains the following values:

/Geography/North America/
/Geography/Asia/Japan/

My goal is to find a “match” between them. A match is performed when any line in set 1 begins with a line in set 2. For example, a match will be made between / Geography / North America / California / San Francisco and / Geography / North America / , because the line from set 1 starts with line from set 2.

I can compare strings using wildcards using a third-party extension. I can also use regex within Xpath.

My problem is, how can I structure the Xpath for selection using a function between all nodes of both sets? XSL is also a viable option.

This XPATH:

count($set1[.=$set2])

Assume the intersection counter between set1 and set2, but this is a 1 to 1 comparison. Can I use some other ways to compare nodes?

EDIT: I got this work, but I'm cheating using some other third-party extensions to get the same result. I'm still interested in other methods to do this.

+3
source share
4 answers

It:

<xsl:variable name="matches" select="$set1[starts-with(., $set2)]"/>

$matches node -set, node $set1, node $set2. , , ?

Edit:

, . .

starts-with , . , .

node -set , node -set, node . , $set2 ; node - , $set1, node $set2.

, ( ) :

<xsl:variable name="hits" select="$set1[. = $set2]"/>

node -sets, .

. : " node $set1, node $set2, ...", , XPath . ? , , - :

<xsl:variable name="matches" select="$set1[$set2[starts-with(?, .)]]"/>

, ?, node, . ( - .)

, , node:

<xsl:variable name="matches">
  <xsl:for-each select="$set1">
    <xsl:if test="$set2[starts-with(current(), .)]">
      <xsl:copy-of select="."/>
    </xsl:if>
  </xsl:for-each>
</xsl:variable>

, , node -set. (, msxsl:node-set) RTF node -set, XPath.

+2

XSLT 1.0 ( ) :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:variable name="vStars">
            <xsl:for-each select="*/regions/*">
                <xsl:for-each select="/*/cities/*[starts-with(.,current())]">
                    <xsl:value-of select="'*'"/>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:variable>

        <xsl:value-of select="string-length($vStars)"/>
    </xsl:template>
</xsl:stylesheet>

XML-:

<t>
    <cities>
        <city>/Geography/North America/California/San Francisco</city>
        <city>/Geography/Asia/Japan/Tokyo/Shinjuku</city>
    </cities>
    <regions>
        <region>/Geography/North America/</region>
        <region>/Geography/Asia/Japan/</region>
    </regions>
</t>

:

2

, (), $vStars. string-length().

+1

last xsl:variable , , ( ), EXSLT MS XSLT 1.0 RTF node, .

XSLT, , , , 1, node 2 :

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes" method="text"/>

  <xsl:template match="/">
    <xsl:call-template name="count-matches">
      <xsl:with-param name="set1-node" select="sets/set[1]/text[1]"/>
      <xsl:with-param name="set2-node" select="sets/set[2]/text[1]"/>
      <xsl:with-param name="total-count" select="0"/>
    </xsl:call-template>
    <xsl:text>
</xsl:text>
  </xsl:template>

  <xsl:template name="count-matches">
    <xsl:param name="set1-node"/>
    <xsl:param name="set2-node"/>
    <xsl:param name="total-count" select="0"/>
    <xsl:variable name="this-count">
      <xsl:choose>
        <xsl:when test="contains($set1-node, $set2-node)">
          <xsl:value-of select="1"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="0"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$set2-node/following-sibling::text">
        <xsl:call-template name="count-matches">
          <xsl:with-param name="set1-node"
                          select="$set1-node"/>
          <xsl:with-param name="set2-node"
                          select="$set2-node/following-sibling::text[1]"/>
          <xsl:with-param name="total-count"
                          select="$total-count + $this-count"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$set1-node/following-sibling::text">
        <xsl:call-template name="count-matches">
          <xsl:with-param name="set1-node"
                          select="$set1-node/following-sibling::text[1]"/>
          <xsl:with-param name="set2-node"
                          select="$set2-node/preceding-sibling::text[last()]"/>
          <xsl:with-param name="total-count"
                          select="$total-count + $this-count"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$total-count + $this-count"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

, XSLT , . XSLT 1.0, , Zack, xsl:for-each.

0

I think I could not get XPath to work on this. I started with the following XML document to initialize two nodes:

<?xml version="1.0"?>
<sets>
  <set>
    <text>/Geography/North America/California/San Francisco</text>
    <text>/Geography/Asia/Japan/Tokyo/Shinjuku</text>
  </set>
  <set>
    <text>/Geography/North America/</text>
    <text>/Geography/Asia/Japan/</text>
  </set>
</sets>

I think this stylesheet should implement Robert's solution, but I only get the score "1":

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:variable name="set1" select="sets/set[1]/text/text()"/>
    <xsl:variable name="set2" select="sets/set[2]/text/text()"/>
    <xsl:value-of select="count($set1[starts-with(., $set2)])"/>
    <xsl:text>
</xsl:text>
  </xsl:template>

</xsl:stylesheet>

I wrote a style sheet that uses a recursive template, and gives the correct score "2" with this input document, but it is much less elegant than Robert. If I could get XPath to work, always wanting to learn.

-1
source

Source: https://habr.com/ru/post/1699238/


All Articles