我需要一个转换以下XML的XSLT 1.0。
<Record>
<Row>
<Name>AAA</Name>
<Surname>Surname1</Surname>
</Row>
<Row>
<Name>BBB</Name>
<Surname>Surname2</Surname>
</Row>
<Row>
<Name>CCC</Name>
<Surname>Surname1</Surname>
</Row>
<Row>
<Name>DDD</Name>
<Surname>Surname2</Surname>
</Row>
<Row>
<Name>EEE</Name>
<Surname>Surname1</Surname>
</Row>
<Row>
<Name>FFF</Name>
<Surname>Surname2</Surname>
</Row>
<Row>
<Name>GGG</Name>
<Surname>Surname1</Surname>
</Row>
<Row>
<Name>HHH</Name>
<Surname>Surname2</Surname>
</Row>
</Record>
我期待的输出是:
<Output>
<Recordset1>
<Record>
<Name>AAA</Name>
<Surname>Surname1</Surname>
</Record>
<Record>
<Name>CCC</Name>
<Surname>Surname1</Surname>
</Record>
</Recordset1>
<Recordset1>
<Record>
<Name>EEE</Name>
<Surname>Surname1</Surname>
</Record>
<Record>
<Name>GGG</Name>
<Surname>Surname1</Surname>
</Record>
</Recordset1>
<Recordset2>
<Record>
<Name>BBB</Name>
<Surname>Surname2</Surname>
</Record>
<Record>
<Name>DDD</Name>
<Surname>Surname2</Surname>
</Record>
</Recordset2>
<Recordset2>
<Record>
<Name>FFF</Name>
<Surname>Surname2</Surname>
</Record>
<Record>
<Name>HHH</Name>
<Surname>Surname2</Surname>
</Record>
</Recordset2>
</Output>
条件是:
Recordset1应包含Surname1节点
Recordset2应包含Surname2节点
输出应按姓氏
每个记录集最多有2个记录。
答案 0 :(得分:0)
这可能会对你有帮助。
<script>
var margin = {top: 8, right: 10, bottom: 2, left: 10},
width = 1160 - margin.left - margin.right,
height = 100 - margin.top - margin.bottom;
var parseDate = d3.timeParse("%H:%M:%S");
var x = d3.scaleTime()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var area = d3.area()
.x(function (d) {
return x(d.time);
})
.y0(height)
.y1(function (d) {
return y(d.stress);
});
var line = d3.line()
.x(function (d) {
return x(d.time);
})
.y(function (d) {
return y(d.stress);
});
d3.csv("6000smokedData3.csv", type, function (error, data) {
// Nest data by date.
var dates = d3.nest()
.key(function (d) {
return d.date;
})
.entries(data);
// Compute the maximum stress per date, needed for the y-domain.
dates.forEach(function (s) {
s.maxPrice = d3.max(s.values, function (d) {
return d.stress;
});
});
// Compute the minimum and maximum time across dates.
// We assume values are sorted by time.
x.domain([
d3.min(dates, function (s) {
return s.values[0].time;
}),
d3.max(dates, function (s) {
return s.values[s.values.length - 1].time;
})
]);
// Add an SVG element for each date, with the desired dimensions and margin.
var svg = d3.select("body").selectAll("svg")
.data(dates)
.enter().append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Add the scatterplot
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 4)
.style("fill", function (d) {
return "red";
})
.attr("cx", function (d) {
if (d.smoked == 1) {
return x(d.time);
}
})
.attr("cy", function (d) {
if (d.smoked == 1) {
return y(d.stress);
}
});
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
// Add the area path elements. Note: the y-domain is set per element.
svg.append("path")
.attr("class", "area")
.attr("d", function (d) {
y.domain([0, d.maxPrice]);
return area(d.values);
});
// Add the line path elements. Note: the y-domain is set per element.
svg.append("path")
.attr("class", "line")
.attr("d", function (d) {
y.domain([0, d.maxPrice]);
return line(d.values);
});
// Add a small label for the date name.
svg.append("text")
.attr("x", width - 6)
.attr("y", height - 6)
.style("text-anchor", "end")
.text(function (d) {
return d.key;
});
});
function type(d) {
d.stress = +d.stress;
d.time = parseDate(d.time);
d.smoked = +d.smoked;
return d;
}
</script>
答案 1 :(得分:0)
有一些技巧:
此样式表解决了这些问题:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Record">
<Output>
<xsl:apply-templates select="//Row[not(./Surname=preceding::Surname)]/Surname" mode="group">
<xsl:sort select="Surname" />
</xsl:apply-templates>
</Output>
</xsl:template>
<xsl:template match="Surname" mode="group">
<xsl:variable name="surname" select="./text()" />
<xsl:variable name="surnameIndex" select="position()" />
<xsl:variable name="surnameGroup" select="/Record/Row[Surname/text()=$surname]" />
<xsl:for-each select="$surnameGroup">
<xsl:variable name="index" select="position()" />
<!-- only create a new record set on the first (or only) member of the output pair -->
<xsl:if test="$index mod 2=1"> <!-- positions are 1 based, not 0 based -->
<xsl:element name="Recordset{$surnameIndex}">
<!-- alternatively, use xsl:copy-of -->
<xsl:apply-templates select="$surnameGroup[$index]" mode="record" />
<xsl:apply-templates select="$surnameGroup[$index+1]" mode="record" />
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="Row" mode="record">
<Record>
<Name><xsl:value-of select="Name" /></Name>
<Surname><xsl:value-of select="Surname" /></Surname>
</Record>
</xsl:template>
</xsl:stylesheet>
对输入文档应用此样式表的输出是:
<?xml version="1.0" encoding="UTF-8" ?>
<Output>
<Recordset1>
<Record>
<Name>AAA</Name>
<Surname>Surname1</Surname>
</Record>
<Record>
<Name>CCC</Name>
<Surname>Surname1</Surname>
</Record>
</Recordset1>
<Recordset1>
<Record>
<Name>EEE</Name>
<Surname>Surname1</Surname>
</Record>
<Record>
<Name>GGG</Name>
<Surname>Surname1</Surname>
</Record>
</Recordset1>
<Recordset2>
<Record>
<Name>BBB</Name>
<Surname>Surname2</Surname>
</Record>
<Record>
<Name>DDD</Name>
<Surname>Surname2</Surname>
</Record>
</Recordset2>
<Recordset2>
<Record>
<Name>FFF</Name>
<Surname>Surname2</Surname>
</Record>
<Record>
<Name>HHH</Name>
<Surname>Surname2</Surname>
</Record>
</Recordset2>
</Output>