xml search and replace xsl errors

拜拜、爱过 提交于 2019-12-12 04:19:21

问题


<?xml version="1.0" encoding="UTF-8"?>
<TABLE NAME="less.db">
   <DATA RECORDS="233673">
      <RECORD ID="1">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>ASUS</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
      <RECORD ID="1">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>asus</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
      <RECORD ID="14">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>Creative Labs</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
      <RECORD ID="1">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>Creative</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
      <RECORD ID="14">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>This is a test. Replace (all)</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
   </DATA>
</TABLE>

search.txt:

ASUS
creative
This is a test. Replace (all)

replace.txt

GIGABYTE
LOGITECH
REPLACEMENT

and the xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:functx="http://www.functx.com"
    exclude-result-prefixes="xs functx"
    version="2.0">

    <xsl:param name="search-file" as="xs:string" select="'search.txt'"/>
    <xsl:param name="replacement-file" as="xs:string" select="'replace.txt'"/>


    <xsl:param name="search-terms" as="xs:string*" select="tokenize(unparsed-text($search-file), '\r?\n')"/>

    <xsl:param name="search-terms-is" as="xs:string*" select="for $term in $search-terms return lower-case(functx:escape-for-regex($term))"/>

    <xsl:param name="replace-terms" as="xs:string*" select="tokenize(unparsed-text($replacement-file), '\r?\n')"/>

    <xsl:include href="http://www.xsltfunctions.com/xsl/functx-1.0-nodoc-2007-01.xsl"/>

    <xsl:function name="functx:replace-multi" as="xs:string?"
        xmlns:functx="http://www.functx.com">
        <xsl:param name="arg" as="xs:string?"/>
        <xsl:param name="changeFrom" as="xs:string*"/>
        <xsl:param name="changeTo" as="xs:string*"/>
        <xsl:param name="flags" as="xs:string"/>

        <xsl:sequence select="
            if (count($changeFrom) > 0)
            then functx:replace-multi(
            replace($arg, $changeFrom[1],
            functx:if-absent($changeTo[1],''), $flags),
            $changeFrom[position() > 1],
            $changeTo[position() > 1])
            else $arg
            "/>

    </xsl:function>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="MANUFACTURER[some $search-term in $search-terms-is satisfies matches(current(), $search-term, 'i')]">
        <xsl:copy>
            <xsl:variable name="matched-terms" as="xs:string*" select="$search-terms-is[matches(current(), ., 'i')]"/>
            <xsl:variable name="replacements" as="xs:string*" select="for $t in $matched-terms return $replace-terms[position() = index-of($search-terms-is, $t)]"/>
            <xsl:value-of
                select="functx:replace-multi(., $matched-terms, $replacements, 'i')"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

gives as output, the following:

<?xml version="1.0" encoding="UTF-8"?>
 <TABLE NAME="less.db">
   <DATA RECORDS="233673">
      <RECORD ID="1">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>GIGABYTE</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
      <RECORD ID="1">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>GIGABYTE</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
      <RECORD ID="14">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>LOGITECH Labs</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
      <RECORD ID="1">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>LOGITECH</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
      <RECORD ID="14">
         <ID>1</ID>
         <ROW>0</ROW>
         <DATE>19/9/2003 12:31:54 μμ</DATE>
         <al>29/6/2005 10:46:42 πμ</al>
         <KIT>46123</KIT>
         <KAP>08</KAP>
         <YTE>A.IV.C.54</YTE>
         <HTE>0</HTE>
         <HEN>0</HEN>
         <SUM>0</SUM>
         <LYW>0</LYW>
         <AMF>29</AMF>
         <MANUFACTURER>REPLACEMENT</MANUFACTURER>
         <AME>pan</AME>
      </RECORD>
   </DATA>
</TABLE>

How should the used xsl be made, so as to have an exact search and replace? for example, LOGITECH Labs is an undesired replacement. We wanted to replace only each element that has exactly the word creative (case insensitive replacement), and not this word, wherever it may be found in the MANUFACTURER element


回答1:


I think the error might be caused by elements containing more than one search term, here is an adapted code sample that hopefully does not give that error:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:functx="http://www.functx.com"
    exclude-result-prefixes="xs functx"
    version="2.0">

    <xsl:param name="search-file" as="xs:string" select="'search.txt'"/>
    <xsl:param name="replacement-file" as="xs:string" select="'replace.txt'"/>


    <xsl:param name="search-terms" as="xs:string*" select="tokenize(unparsed-text($search-file), '\r?\n')"/>

    <xsl:param name="search-terms-is" as="xs:string*" select="for $term in $search-terms return lower-case(functx:escape-for-regex($term))"/>

    <xsl:param name="replace-terms" as="xs:string*" select="tokenize(unparsed-text($replacement-file), '\r?\n')"/>

    <xsl:include href="http://www.xsltfunctions.com/xsl/functx-1.0-nodoc-2007-01.xsl"/>

    <xsl:function name="functx:replace-multi" as="xs:string?"
        xmlns:functx="http://www.functx.com">
        <xsl:param name="arg" as="xs:string?"/>
        <xsl:param name="changeFrom" as="xs:string*"/>
        <xsl:param name="changeTo" as="xs:string*"/>
        <xsl:param name="flags" as="xs:string"/>

        <xsl:sequence select="
            if (count($changeFrom) > 0)
            then functx:replace-multi(
            replace($arg, $changeFrom[1],
            functx:if-absent($changeTo[1],''), $flags),
            $changeFrom[position() > 1],
            $changeTo[position() > 1])
            else $arg
            "/>

    </xsl:function>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="MANUFACTURER[some $search-term in $search-terms-is satisfies matches(current(), $search-term, 'i')]">
        <xsl:copy>
            <xsl:variable name="matched-terms" as="xs:string*" select="$search-terms-is[matches(current(), ., 'i')]"/>
            <xsl:variable name="replacements" as="xs:string*"
                select="for $t in $matched-terms return $replace-terms[index-of($search-terms-is, $t)]"/>
            <xsl:value-of
                select="functx:replace-multi(., $matched-terms, $replacements, 'i')"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>


来源:https://stackoverflow.com/questions/44538226/xml-search-and-replace-xsl-errors

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!