Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基本XML/XSLT转换:搜索和;代替_Xml_Xslt - Fatal编程技术网

基本XML/XSLT转换:搜索和;代替

基本XML/XSLT转换:搜索和;代替,xml,xslt,Xml,Xslt,我不熟悉XML和XSLT,并且花了一些时间研究了一个非常简单的搜索和替换案例。我只是不知道语法是否正确 本练习的总体目标是将元素“NewCustomer”中的“Y”和“N”的值分别替换为“true”或“false” 这是我的样本数据 <?xml version="1.0"?> <CustomerList> <Customer> <CustomerID>1111</CustomerID> <CompanyName

我不熟悉XML和XSLT,并且花了一些时间研究了一个非常简单的搜索和替换案例。我只是不知道语法是否正确

本练习的总体目标是将元素“NewCustomer”中的“Y”和“N”的值分别替换为“true”或“false”

这是我的样本数据

<?xml version="1.0"?>
<CustomerList>
  <Customer>
    <CustomerID>1111</CustomerID>
    <CompanyName>Sean Chai</CompanyName>
    <City>New York</City>
    <NewCustomer>N</NewCustomer>
    </Customer>
  <Customer>
    <CustomerID>1112</CustomerID>
    <CompanyName>Tom Johnston</CompanyName>
    <City>Los Angeles</City>
    <NewCustomer>N</NewCustomer>
  </Customer>
  <Customer>
    <CustomerID>1113</CustomerID>
    <CompanyName>Institute of Art</CompanyName>
    <City>Chicago</City>
    <NewCustomer>Y</NewCustomer>
  </Customer>
</CustomerList>

1111
肖恩柴
纽约
N
1112
汤姆强斯顿
洛杉矶
N
1113
艺术学院
芝加哥
Y
这是转换样式表

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

  <!-- Identity Template (applies to all nodes and will copy all nodes -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Customer">
    <xsl:choose>
      <xsl:when test="NewCustomer = 'Y'">
        <xsl:text>true</xsl:text>
      </xsl:when>
      <xsl:when test="NewCustomer = 'N'">
        <xsl:text>false</xsl:text>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

真的
假的
这是我的输出

  <?xml version="1.0" encoding="utf-8" ?> 
  <CustomerList>false false true</CustomerList> 

假假假真
下面是我希望它输出的内容

<?xml version="1.0"?>
<CustomerList>
  <Customer>
    <CustomerID>1111</CustomerID>
    <CompanyName>Sean Chai</CompanyName>
    <City>New York</City>
    <NewCustomer>false</NewCustomer>
  </Customer>
  <Customer>
    <CustomerID>1112</CustomerID>
    <CompanyName>Tom Johnston</CompanyName>
    <City>Los Angeles</City>
    <NewCustomer>false</NewCustomer>
  </Customer>
  <Customer>
    <CustomerID>1113</CustomerID>
    <CompanyName>Institute of Art</CompanyName>
    <City>Chicago</City>
    <NewCustomer>true</NewCustomer>
  </Customer>
</CustomerList>

1111
肖恩柴
纽约
假的
1112
汤姆强斯顿
洛杉矶
假的
1113
艺术学院
芝加哥
真的

我错过了什么?为什么?我发现如果我省略了检查NewCustomer的子句,那么整个输出都会得到输出。但是,选择为NewCustomer输出正确更改的值只会显示这些值。我必须在第二个模板中引用上一个模板吗?

通过让模板与客户匹配,您将拦截该标记的所有处理

尝试更改模板以仅匹配NewCustomer,并在测试条件中进行相应更改(test=“.=”Y')

还要注意,您必须在输出中创建NewCustomer标记,因为通过在自定义模板中匹配它,标识转换不会处理它。你很接近

以下是更新的模板:

<xsl:template match="Customer/NewCustomer">
    <xsl:copy>
        <xsl:choose>
            <xsl:when test=". = 'Y'">
                <xsl:text>true</xsl:text>
            </xsl:when>
            <xsl:when test=". = 'N'">
                <xsl:text>false</xsl:text>
            </xsl:when>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

真的
假的
首先,它将NewCustomer作为Customer的子级进行匹配。然后,它使用xsl:copy创建节点的副本(而不是属性或子节点)。然后使用xsl:choose将N和Y值分别转换为false和true


关键概念是,当模板与输入元素匹配时,输入元素将从输出中有效删除,并替换为匹配模板的内容。在您的案例中,当您匹配客户时,客户标签及其内部的所有内容都被模板的内容所替换,而模板的内容只是生成了“真”或“假”。

吉姆·加里森回答中的精彩解释仍然适用。以下是一种浓缩/替代方法:

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

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:choose>
        <xsl:when test="self::NewCustomer">
          <xsl:value-of select="boolean(number(translate(., 'YN', '10')))" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

表达式
boolean(number(translate(,'YN','10'))
'Y'
更改为
'1'
,将
'N'
更改为
'0'
,然后将其首先转换为数字,然后再转换为布尔值。布尔值将分别表示为
'true'
'false'

这有点脏,因为它实际上不处理除
'Y'
'N'
以外的值,但它将为
'Y'
以外的任何值输出
'false'


这只不过是节省空间而已。如果您愿意,您可以用Jim Garrison使用的
替换它。

Jim Garrison将从任何
新客户
元素中删除属性。而托马拉克的,正如他所说的,有点脏

此版本几乎是将您的需求直译为XSLT:

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

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

  <xsl:template match="NewCustomer/text()[.='Y']">
   <xsl:text>true</xsl:text>
  </xsl:template>

 <xsl:template match="NewCustomer/text()[.='N']">
    <xsl:text>false</xsl:text>
  </xsl:template>

</xsl:stylesheet>

真的
假的

源树中唯一没有准确复制到结果集中的节点是文本节点,这些节点是
NewCustomer
元素的子元素,其值为
Y
N
;对于这些,它分别发出
true
false

+1完成这项任务的方法确实很多。我从给定的数据中“假设”了模式,没有复制属性。关于问题的“如何/为什么”部分,请参阅@JimGarrison答案。