我是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>
这是转换样式表。
<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>
我想念的是什么?为什么?我看到如果我省略了检查NewCustomer的子句,整个输出就会输出。但是,选择为NewCustomer输出正确更改的值只会显示它们。是否有对我必须在第二个模板中创建的上一个模板的引用?
答案 0 :(得分:4)
Jim Garrison将删除任何包含它们的NewCustomer
元素的属性。正如他所说的那样,Tomalak有点脏。
此版本几乎是您对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 :(得分:3)
通过让您的模板与Customer匹配,您将拦截该标记的所有处理。
尝试更改模板以仅匹配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:选择将N和Y值分别转换为false和true。
关键概念是当模板与输入元素匹配时,输入元素将从输出中有效删除,并替换为匹配模板的内容。在您与Customer匹配的情况下,Customer标记及其中的所有内容都替换为模板的内容,该模板只生成“true”或“false”。
答案 2 :(得分:0)
吉姆加里森的答案中的好解释仍然适用。这是一种浓缩/替代方法:
<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'
以外的值 - 但它会为'false'
以外的任何值输出'Y'
。
这只是一个节省空间。如果你愿意,你可以用像Jim Garrison这样的<xsl:choose>
替换它。