У меня есть следующая проблема, которая для меня немного сложна,
В основном мне нужно иметь возможность изменять входной файл XML с данными, которые я сохранил в другом XML-файле, поэтому мне нужно будет использовать 2 входных файла XML,
У меня есть следующий XML-файл, который я хочу изменить (в основном, просто добавив в него):
<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23" id="1">
<text-prop name="displayName">PersonTemplate</text-prop>
<setup>
<simple-master-page name="MasterPage" id="2">
<footer>
<text id="3">
<prop name="contentType">html</prop>
<text-prop name="content"><![CDATA[<value-of>new Date()</value-of>]]></text-prop>
</text>
</footer>
</simple-master-page>
</setup>
<body>
<table id="4">
<column id="17"/>
<column id="18"/>
<column id="19"/>
<header>
<row id="5">
<cell id="6">
<label id="20">
<text-prop name="text">NameTitle</text-prop>
</label>
</cell>
<cell id="7">
<label id="21">
<text-prop name="text">CityTitle</text-prop>
</label>
</cell>
<cell id="8">
<label id="22">
<text-prop name="text">AgeTitle</text-prop>
</label>
</cell>
</row>
</header>
<detail>
<row id="9">
<cell id="10"/>
<cell id="11"/>
<cell id="12"/>
</row>
</detail>
</table>
</body>
</report>
И я хочу внести в него изменения / дополнения, обратившись к другому XML-файлу, который дает мне данные, которые я хочу поместить в первый XML-файл:
<?xml version="1.0" encoding="utf-8"?>
<model>
<layouts>
<layout ID="001" name="PersonTemplate" format="Table" nFields="3" >
<fields>
<field name="NameTitle"/>
<field name="CityTitle"/>
<field name="AgeTitle"/>
</fields>
</layout>
<layout ID="002" name="SchoolTemplate" format="Table" nFields="3" >
<fields>
<field name="NameTitle"/>
<field name="LocationTitle"/>
<field name="MaxCapacityTitle"/>
</fields>
</layout>
</layouts>
<reports>
<report layoutID="001">
<params>
<sources>
<source name="source1" dbURL="sampledb1.com" user="user1" password="dXNlcjE=" driver="dbDriver"/>
<source name="source2" dbURL="sampledb2.com" user="user2" password="dXNlcjI=" driver="dbDriver"/>
</sources>
<set name="set1" source="source1" querie="select Name, City, Age from PeopleTable" >
<qFields>
<qField name="Name" type="string"/>
<qField name="City" type="string"/>
<qField name="Age" type="integer"/>
</qFields>
</set>
</params>
</report>
<report layoutID="002">
<params>
<sources>
<source name="source1" dbURL="sampledb1.com" user="user1" password="dXNlcjE=" driver="dbDriver"/>
</sources>
<set name="Data Set" dataSource="source1" querie="select Name, Location, MaxCapacity from SchoolsTable" >
<qFields>
<qField name="Name" type="string"/>
<qField name="Location" type="string"/>
<qField name="MaxCapacity" type="integer"/>
</qFields>
</set>
</params>
</report>
</reports>
</model>
Итак, я хочу создать следующий XML-файл:
<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23" id="1">
<text-prop name="displayName">PersonTemplate</text-prop>
<data-sources>
<data-source extensionID="this.is.a.fixed.value" name="source1">
<prop name="DriverClass">dbDriver</prop>
<prop name="databaseURL">sampledb1.com</prop>
<prop name="dbUser">user1</prop>
<encrypted-prop name="dbPassword" encryptionID="base64">dXNlcjE=</encrypted-prop>
</data-source>
</data-sources>
<data-sets>
<data-set extensionID="this.is.a.fixed.value" name="set1">
<list-prop name="columnHints">
<struct>
<prop name="columnName">Name</prop>
<text-prop name="displayName">Name</text-prop>
<text-prop name="heading">Name</text-prop>
</struct>
<struct>
<prop name="columnName">City</prop>
<text-prop name="displayName">City</text-prop>
<text-prop name="heading">City</text-prop>
</struct>
<struct>
<prop name="columnName">Age</prop>
<text-prop name="displayName">Age</text-prop>
<text-prop name="heading">Age</text-prop>
</struct>
</list-prop>
<struct name="cachedMetaData">
<list-prop name="resultSet">
<struct>
<prop name="position">1</prop>
<prop name="name">Name</prop>
<prop name="dataType">string</prop>
</struct>
<struct>
<prop name="position">2</prop>
<prop name="name">City</prop>
<prop name="dataType">string</prop>
</struct>
<struct>
<prop name="position">3</prop>
<prop name="name">Age</prop>
<prop name="dataType">integer</prop>
</struct>
</list-prop>
</struct>
<prop name="dataSource">source1</prop>
<list-prop name="resultSet">
<struct>
<prop name="position">1</prop>
<prop name="name">Name</prop>
<prop name="dataType">string</prop>
</struct>
<struct>
<prop name="position">2</prop>
<prop name="name">City</prop>
<prop name="dataType">string</prop>
</struct>
<struct>
<prop name="position">3</prop>
<prop name="name">AGE</prop>
<prop name="dataType">integer</prop>
</struct>
</list-prop>
<xml-prop name="queryText"><![CDATA[select Name, City, Age from PeopleTable]]></xml-prop>
</data-set>
</data-sets>
<setup>
<simple-master-page name="MasterPage" id="2">
<footer>
<text id="3">
<prop name="contentType">html</prop>
<text-prop name="content"><![CDATA[<value-of>new Date()</value-of>]]></text-prop>
</text>
</footer>
</simple-master-page>
</setup>
<body>
<table id="4">
<prop name="dataSet">set1</prop>
<list-prop name="boundDataColumns">
<struct>
<prop name="name">Name</prop>
<text-prop name="displayName">Name</text-prop>
<expression name="expression" type="javascript">dataSetRow["Name"]</expression>
<prop name="dataType">string</prop>
</struct>
<struct>
<prop name="name">City</prop>
<text-prop name="displayName">City</text-prop>
<expression name="expression" type="javascript">dataSetRow["City"]</expression>
<prop name="dataType">string</prop>
</struct>
<structure>
<prop name="name">Age</prop>
<text-prop name="displayName">Age</text-prop>
<expression name="expression" type="javascript">dataSetRow["Age"]</expression>
<prop name="dataType">integer</prop>
</structure>
</list-prop>
<column id="17"/>
<column id="18"/>
<column id="19"/>
<header>
<row id="5">
<cell id="6">
<label id="20">
<text-prop name="text">NameTitle</text-prop>
</label>
</cell>
<cell id="7">
<label id="21">
<text-prop name="text">CityTitle</text-prop>
</label>
</cell>
<cell id="8">
<label id="22">
<text-prop name="text">AgeTitle</text-prop>
</label>
</cell>
</row>
</header>
<detail>
<row id="9">
<cell id="10">
<data>
<prop name="resultSetColumn">Name</prop>
</data>
</cell>
<cell id="11">
<data>
<prop name="resultSetColumn">City</prop>
</data>
</cell>
<cell id="12">
<data>
<prop name="resultSetColumn">Age</prop>
</data>
</cell>
</row>
</detail>
</table>
</body>
</report>
Примечание: encryptionID
и extensionID
как в источнике данных, так и в наборе данных являются фиксированными значениями.
Таким образом, в основном данные поступают из набора set1
, который использует источник source1
, а также непосредственно из source1
, поэтому мне нужен способ получения правильных данных из второго файла XML.
Как видите, у меня может быть много элементов layout
и report
во втором XML-файле. Итак, сначала я думаю, что мне нужно найти свойство displayName
в первом XML-файле, а затем найти элемент layout
, в котором атрибут name
соответствует displayName
. Затем мне нужно во втором XML-файле по атрибуту ID
в элементе layout
найти элемент report
, который имеет то же значение в атрибуте layoutID
. С этого момента я бы нашел правильный report
элемент. Только сейчас я бы начал изменять / вносить дополнения в первый XML-файл. Эту часть я действительно не знаю, как это сделать. Возможно ли то, что я пытаюсь сделать?
Я знаю, что вы можете использовать функцию document
для работы с 2 файлами XML, но я не знаю, как,
Мне очень нужна помощь, ребята, спасибо!
EDIT
В основном я хочу скопировать все в первый файл XML ( уже сделано ), а затем добавить к нему данные, хранящиеся во втором файле XML (тот, который начинается с элемента <model>
*
UPDATE
Поскольку я хочу, чтобы вывод был дополнением к первому входному XML-файлу, я начал, как рекомендовал @Sojimanatsu, с применения преобразования идентификаторов, например, (с помощью @ TimC в сообщении по конкретной проблеме специальные символы ( XML - XSLT - экранирование специальных символов )):
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xmlbirtns="http://www.eclipse.org/birt/2005/design"
xpath-default-namespace="http://www.eclipse.org/birt/2005/design">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="utf-8" />
<xsl:strip-space elements="*"/>
<!--copy the whole input XML file-->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--special treatment for setup/text-prop element-->
<xsl:template match="report/setup/simple-master-page/footer/text/text-prop">
<xsl:copy>
<xsl:attribute name="name">
<xsl:text>content</xsl:text>
</xsl:attribute>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:value-of select="." disable-output-escaping="yes"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
ПРИМЕЧАНИЕ: Код XSLT, относящийся к элементу setup / text-prop, является необязательным, поскольку мой выходной XML может иметь <value-of>new Date()</value-of>
вместо <![CDATA[<value-of>new Date()</value-of>]]>
Так что теперь я могу печатать в выходном XML именно то, что есть в первом входном XML. Теперь, как сказал @Sojimanatsu, я хочу выбрать определенные теги и редактировать их с новыми данными, поступающими из входного XML-файла sencond, а также хочу добавить новые теги / элементы, такие как элементы data-sources
и data-sets
, но Я не знаю, как это сделать. Я знаю, что должен использовать функцию document (), но как ??
Для начала, как я могу добавить новый элемент, <data-sources>
ниже элемента <report>
и перед элементом <setup>
? (<data-sources>
и <setup>
являются братьями и сестрами)
Я попытался сделать это, добавив новое <xsl:template>
:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xmlbirtns="http://www.eclipse.org/birt/2005/design"
xpath-default-namespace="http://www.eclipse.org/birt/2005/design">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="utf-8" />
<xsl:strip-space elements="*"/>
<!--copy the whole input XML file-->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--special treatment for setup/text-prop element-->
<xsl:template match="report/setup/simple-master-page/footer/text/text-prop">
<xsl:copy>
<xsl:attribute name="name">
<xsl:text>content</xsl:text>
</xsl:attribute>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:value-of select="." disable-output-escaping="yes"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:copy>
</xsl:template>
<xsl:template match="report/text-prop">
<xsl:copy-of select="."/>
<dataSources>DATA SOURCE VALUE</dataSources>
</xsl:template>
</xsl:stylesheet>
Но я получаю этот вывод (тег dataSource находится в правильном месте, но с некоторыми атрибутами, которые я не знаю, как туда попал):
<?xml version="1.0" encoding="utf-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23" id="1">
<text-prop name="displayName">PersonTemplate</text-prop>
<dataSources xmlns=""
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xmlbirtns="http://www.eclipse.org/birt/2005/design">DATA SOURCE VALUE</dataSources>
<setup>
<simple-master-page name="MasterPage" id="2">
<footer>
<text id="3">
<prop name="contentType">html</prop>
<text-prop name="content"><![CDATA[<value-of>new Date()</value-of>]]></text-prop>
</text>
</footer>
</simple-master-page>
</setup>
<body>
<table id="4">
<column id="17"/>
<column id="18"/>
<column id="19"/>
<header>
<row id="5">
<cell id="6">
<label id="20">
<text-prop name="text">NameTitle</text-prop>
</label>
</cell>
<cell id="7">
<label id="21">
<text-prop name="text">CityTitle</text-prop>
</label>
</cell>
<cell id="8">
<label id="22">
<text-prop name="text">AgeTitle</text-prop>
</label>
</cell>
</row>
</header>
<detail>
<row id="9">
<cell id="10"/>
<cell id="11"/>
<cell id="12"/>
</row>
</detail>
</table>
</body>
</report>
Мои настоящие первый и второй входные XML-файлы значительно больше, но как только у меня будет работать этот пример, я могу создать свой настоящий XML-вывод,
Спасибо, ребята!