#xml #xslt
#xml #xslt
Вопрос:
Я пытался переместить атрибут из одного элемента в другой, но вместо этого он создает другой дочерний элемент.
У меня есть следующее
<wrapper>
<Person ID="1">
<Person InfoName="bob" Gender="male" />
<Purchase Reference = "1" Item="book"/>
<Purchase Reference = "2" Item="shoes"/>
</Person>
<Person ID="2">
<Person InfoName="Jane" Gender="female"/>
<Purchase Reference = "1" Item="pen"/>
<Purchase Reference = "2" Item="hat"/>
</Person>
</wrapper>
и мне нужно иметь следующее (я не беспокоюсь о сохранении, поскольку все записи будут иметь идентификатор):
<wrapper>
<Person ID="1">
<Person InfoName="bob" Gender="male" ID = "1"/>
<Purchase Reference = "1" Item="book" ID="1"/>
<Purchase Reference = "2" Item="shoes" ID="1"/>
</Person>
<Person ID="2">
<Person InfoName="Jane" Gender="female" ID="2"/>
<Purchase Reference = "1" Item="pen" ID="2"/>
<Purchase Reference = "2" Item="hat" ID="2"/>
</Person>
</wrapper>
Я пробовал несколько разных XSLT с разной степенью успеха. Следующее создает новый дочерний узел.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@ID]">
<xsl:copy>
<xsl:apply-templates select="@*[name() != 'ID']" />
<xsl:element name="{name()}ID">
<xsl:value-of select="@ID" />
</xsl:element>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
Комментарии:
1. Ваш ввод не является правильно сформированным XML!
2. Большое вам спасибо за ответ, который ценится …. цель преобразования заключалась в том, чтобы я мог импортировать и XML-файл в access для дальнейшего изучения, с тех пор я использовал XML Spy для этого, и поэтому XSLT больше не требуется…
3. И.Алам, посмотрите решение, в котором добавленный
ID
атрибут является последним — как и требовалось в вашем вопросе. Два других решения помещают его в качестве первого …4. В спецификации XML явно указано, что порядок атрибутов не имеет значения. Процессор XSLT может выводить их в любом порядке. Пытаться контролировать порядок с помощью таблицы стилей XSLT бессмысленно; то, что работает с одним процессором, может не работать с другим.
Ответ №1:
(1) Позаботьтесь о допустимом xml. Атрибуты должны быть парой Ключ-значение, например info="a"
(значение должно быть в "
). XML чувствителен к регистру.
(2) Ваше решение намного проще:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="wrapper/Person/*">
<xsl:copy>
<xsl:apply-templates select="@* | ../@ID"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Выберите свои элементы для копирования в via wrapper/Person/*
и grep атрибут ID
родительского via ..
.
Комментарии:
1. Большое вам спасибо за ответ, который ценится …. цель преобразования заключалась в том, чтобы я мог импортировать и XML-файл в access для дальнейшего изучения, с тех пор я использовал XML Spy для этого, и поэтому XSLT больше не требуется
Ответ №2:
Попробуйте сделать это так:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Person/*">
<xsl:copy>
<xsl:apply-templates select="@*|../@ID|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Применяется к следующему правильно сформированному вводу:
<Wrapper>
<Person ID ="1">
<Person Name="bob" Gender="male" />
<Purchase Reference = "1" Item="book"/>
<Purchase Reference = "2" Item="shoes"/>
</Person>
<Person ID ="2">
<Person Name="Jane" Gender="female"/>
<Purchase Reference = "1" Item="pen"/>
<Purchase Reference = "2" Item="hat"/>
</Person>
</Wrapper>
результатом будет:
<?xml version="1.0" encoding="UTF-8"?>
<Wrapper>
<Person ID="1">
<Person ID="1" Name="bob" Gender="male"/>
<Purchase ID="1" Reference="1" Item="book"/>
<Purchase ID="1" Reference="2" Item="shoes"/>
</Person>
<Person ID="2">
<Person ID="2" Name="Jane" Gender="female"/>
<Purchase ID="2" Reference="1" Item="pen"/>
<Purchase ID="2" Reference="2" Item="hat"/>
</Person>
</Wrapper>
Ответ №3:
Пока это единственное решение, которое помещает ID
атрибут последним — как требуется:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Person/*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="../@ID"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
При применении к предоставленному XML-документу:
<wrapper>
<Person ID="1">
<Person InfoName="bob" Gender="male" />
<Purchase Reference = "1" Item="book"/>
<Purchase Reference = "2" Item="shoes"/>
</Person>
<Person ID="2">
<Person InfoName="Jane" Gender="female"/>
<Purchase Reference = "1" Item="pen"/>
<Purchase Reference = "2" Item="hat"/>
</Person>
</wrapper>
Получен точный (не похожий на результаты других решений) желаемый результат:
<wrapper>
<Person ID="1">
<Person InfoName="bob" Gender="male" ID="1"/>
<Purchase Reference="1" Item="book" ID="1"/>
<Purchase Reference="2" Item="shoes" ID="1"/>
</Person>
<Person ID="2">
<Person InfoName="Jane" Gender="female" ID="2"/>
<Purchase Reference="1" Item="pen" ID="2"/>
<Purchase Reference="2" Item="hat" ID="2"/>
</Person>
</wrapper>